static CcwMethodInfo CreateCcwMethod(ComMethodInfo comMethodInfo, TypeBuilder typeBuilder, Utils.UniqueNameGenerator methodNameUniqifier) { var methodInfo = comMethodInfo.MethodInfo; var methodNameTemplate = methodInfo.Name; var methodName = methodNameUniqifier.Uniquify(methodNameTemplate); var paramTypes = new List <Type>(); paramTypes.Add(typeof(IntPtr)); paramTypes.AddRange(comMethodInfo.ParameterInfos.Select((p) => p.IsOut ? p.ValueMarshaller.NativeParameterType.MakePointerType() : p.ValueMarshaller.NativeParameterType)); var methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.HideBySig | MethodAttributes.Static, CallingConventions.Standard, comMethodInfo.NativeReturnType, paramTypes.ToArray()); methodBuilder.DefineParameter(1, ParameterAttributes.In, "this"); // define a method foreach (var parameter in methodInfo.GetParameters()) { methodBuilder.DefineParameter(parameter.Position + 2, parameter.Attributes, parameter.Name); } CreateCcwMethodBody(comMethodInfo, methodBuilder); return(new CcwMethodInfo() { methodBuilder = methodBuilder, parameterTypes = paramTypes.ToArray() }); }
static void ImplementFieldGetter(TypeBuilder typeBuilder, FieldInfo fieldInfo, PropertyInfo genericPropertyInfo, MethodInfo getterMethodInfo, Utils.UniqueNameGenerator methodNameUniqifier) { var propNameTemplate = getterMethodInfo.DeclaringType.Name + "." + genericPropertyInfo.Name; var propName = methodNameUniqifier.Uniquify(propNameTemplate); var prop = typeBuilder.DefineProperty(propName, PropertyAttributes.None, getterMethodInfo.ReturnType, new Type[] { }); var methodNameTemplate = getterMethodInfo.DeclaringType.Name + "." + getterMethodInfo.Name; var methodName = methodNameUniqifier.Uniquify(methodNameTemplate); var methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, getterMethodInfo.ReturnType, new Type[] { }); typeBuilder.DefineMethodOverride(methodBuilder, getterMethodInfo); var gen = methodBuilder.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, fieldInfo); gen.Emit(OpCodes.Ret); prop.SetGetMethod(methodBuilder); }
static void DefineRcwClass(InterfaceInfo interfaceInfo, TypeBuilder typeBuilder) { var type = typeBuilder; var nativeObjectType = typeof(INativeObject <>).GetTypeInfo().MakeGenericType(type); var nativeObjectTypeInfo = nativeObjectType.GetTypeInfo(); typeBuilder.AddInterfaceImplementation(nativeObjectType); foreach (var theInterface in interfaceInfo.AllImplementedInterfaces) { typeBuilder.AddInterfaceImplementation(theInterface); } FieldInfo interfacePtrField = typeBuilder.DefineField("interfacePtr", typeof(IntPtr), 0); FieldInfo unknownPtrField = typeBuilder.DefineField("iUnknownPtr", typeof(IntPtr), 0); // generate constructor var ctor = CreateRcwConstructor(typeBuilder, interfacePtrField, unknownPtrField); // generate finalizer CreateRcwFinalizer(typeBuilder); // generate factory CreateRcwFactoryMethod(typeBuilder, ctor); var methodNameUniqifier = new Utils.UniqueNameGenerator(); methodNameUniqifier.Uniquify("interfacePtr"); methodNameUniqifier.Uniquify("iUnknownPtr"); methodNameUniqifier.Uniquify("Finalize"); methodNameUniqifier.Uniquify("Create"); foreach (var method in interfaceInfo.ComMethodInfos) { CreateRcwMethod(method, typeBuilder, interfacePtrField, methodNameUniqifier); } // implement INativeObject ImplementFieldGetter(typeBuilder, interfacePtrField, nativeInterfacePtrProp, TypeBuilder.GetMethod(nativeObjectType, nativeInterfacePtrProp.GetMethod), methodNameUniqifier); ImplementFieldGetter(typeBuilder, unknownPtrField, nativeIUnknownPtrProp, TypeBuilder.GetMethod(nativeObjectType, nativeIUnknownPtrProp.GetMethod), methodNameUniqifier); ImplementInterfaceProperty(typeBuilder, interfaceProp, TypeBuilder.GetMethod(nativeObjectType, interfaceProp.GetMethod), methodNameUniqifier); }
static void DefineCcwClass(InterfaceInfo interfaceInfo, TypeBuilder typeBuilder) { var type = typeBuilder; var uniqifier = new Utils.UniqueNameGenerator(); uniqifier.Uniquify("Create"); // reserve var methods = new List <CcwMethodInfo>(); foreach (var method in interfaceInfo.ComMethodInfos) { methods.Add(CreateCcwMethod(method, typeBuilder, uniqifier)); } CreateCcwFactoryMethod(typeBuilder, methods.ToArray(), uniqifier); }
static void CreateRcwMethod(ComMethodInfo comMethodInfo, TypeBuilder typeBuilder, FieldInfo ptrFieldInfo, Utils.UniqueNameGenerator methodNameUniqifier) { var methodInfo = comMethodInfo.MethodInfo; var methodNameTemplate = comMethodInfo.MethodInfo.DeclaringType.Name + "." + methodInfo.Name; var methodName = methodNameUniqifier.Uniquify(methodNameTemplate); var methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.Standard, methodInfo.ReturnType, methodInfo.GetParameters().Select((p) => p.ParameterType).ToArray()); typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); // define a method foreach (var parameter in methodInfo.GetParameters()) { methodBuilder.DefineParameter(parameter.Position + 1, parameter.Attributes, parameter.Name); } CreateRCWMethodBody(comMethodInfo, ptrFieldInfo, methodBuilder); }
static MethodBuilder CreateCcwFactoryMethod(TypeBuilder typeBuilder, CcwMethodInfo[] vtable, Utils.UniqueNameGenerator uniqifier) { var nativeObjectType = typeof(INativeObject <>).GetTypeInfo().MakeGenericType(typeBuilder); var methodBuilder = typeBuilder.DefineMethod("Create", MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(IntPtr[]), new Type[] { }); methodBuilder.SetCustomAttribute(securityCriticalAttributeCab); var gen = methodBuilder.GetILGenerator(); gen.Emit(OpCodes.Ldc_I4, vtable.Length); gen.Emit(OpCodes.Newarr, typeof(IntPtr)); for (int i = 0; i < vtable.Length; ++i) { var ccwMethodInfo = vtable[i]; gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Ldc_I4, i); gen.Emit(OpCodes.Ldftn, ccwMethodInfo.methodBuilder); gen.Emit(OpCodes.Stelem, typeof(IntPtr)); // add MonoPInvokeCallbackAttribute so this method is included in // full AOT /*var mpca = new CustomAttributeBuilder(typeof(MonoPInvokeCallbackAttribute) * .GetTypeInfo() * .DeclaredConstructors.First((ctor2) => ctor2.GetParameters().Length == 1), * new object[] { delegateType }); * ccwMethodInfo.methodBuilder.SetCustomAttribute(mpca); * * delegateType.CreateTypeInfo();*/ } gen.Emit(OpCodes.Ret); return(methodBuilder); }