/** * Defines a new MethodBuilder that calls the specified C++ (non-virtual) method using its mangled name */ protected virtual MethodBuilder GetPInvokeForMethod(CppTypeInfo typeInfo, PInvokeSignature sig) { var entryPoint = sig.Name; if (entryPoint == null) { throw new NotSupportedException("Could not mangle method name."); } string lib; if (IsInline(sig.OrigMethod) && typeInfo.Library.InlineMethodPolicy == InlineMethods.SurrogateLib) { lib = typeInfo.Library.Name + "-inline"; } else { lib = typeInfo.Library.Name; } var builder = typeInfo.emit_info.type_builder.DefinePInvokeMethod(entryPoint, lib, entryPoint, MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.PinvokeImpl, CallingConventions.Standard, sig.ReturnType, sig.ParameterTypes.ToArray(), sig.CallingConvention.Value, CharSet.Ansi); builder.SetImplementationFlags(builder.GetMethodImplementationFlags() | MethodImplAttributes.PreserveSig); ReflectionHelper.ApplyMethodParameterAttributes(sig.OrigMethod, builder, true); return(builder); }
/** * Defines a new MethodBuilder with the same signature as the passed MethodInfo */ protected virtual MethodBuilder GetMethodBuilder(CppTypeInfo typeInfo, MethodInfo interfaceMethod) { var parameterTypes = ReflectionHelper.GetMethodParameterTypes(interfaceMethod); var methodBuilder = typeInfo.emit_info.type_builder.DefineMethod(interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, interfaceMethod.ReturnType, parameterTypes); ReflectionHelper.ApplyMethodParameterAttributes(interfaceMethod, methodBuilder, false); return(methodBuilder); }
/** * Implements the managed trampoline that will be invoked from the vtable by native C++ code when overriding * the specified C++ virtual method with the specified managed one. */ // FIXME: This should be moved into CppTypeInfo class internal virtual Delegate GetManagedOverrideTrampoline(CppTypeInfo typeInfo, int vtableIndex) { if (typeInfo.WrapperType == null) { return(null); } var sig = typeInfo.VirtualMethods [vtableIndex]; if (sig == null) { return(null); } var interfaceMethod = sig.OrigMethod; var targetMethod = FindManagedOverrideTarget(typeInfo.WrapperType, interfaceMethod); if (targetMethod == null) { return(null); } var interfaceArgs = ReflectionHelper.GetMethodParameterTypes(interfaceMethod); var nativeArgs = sig.ParameterTypes.ToArray(); // TODO: According to http://msdn.microsoft.com/en-us/library/w16z8yc4.aspx // The dynamic method created with this constructor has access to public and internal members of all the types contained in module m. // This does not appear to hold true, so we also disable JIT visibility checks. var trampolineIn = new DynamicMethod(typeInfo.WrapperType.Name + "_" + interfaceMethod.Name + "_FromNative", sig.ReturnType, nativeArgs, typeof(CppInstancePtr).Module, true); ReflectionHelper.ApplyMethodParameterAttributes(interfaceMethod, trampolineIn, true); var il = trampolineIn.GetILGenerator(); // for static (target) methods: OpCode callInstruction = OpCodes.Call; int argLoadStart = IsStatic(interfaceMethod)? 0 : 1; // chop off C++ instance ptr if there is one // for instance methods, we need a managed instance to call them on! if (!targetMethod.IsStatic) { callInstruction = OpCodes.Callvirt; argLoadStart = 1; il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, typeInfo.GCHandleOffset); var getManagedObj = cppip_tomanaged_size.MakeGenericMethod(typeInfo.WrapperType); il.Emit(OpCodes.Call, getManagedObj); } for (int i = argLoadStart; i < interfaceArgs.Length; i++) { il.Emit(OpCodes.Ldarg, i); EmitInboundMarshal(il, nativeArgs [i], interfaceArgs [i]); } il.Emit(callInstruction, targetMethod); EmitOutboundMarshal(il, targetMethod.ReturnType, sig.ReturnType); il.Emit(OpCodes.Ret); return(trampolineIn.CreateDelegate(typeInfo.VTableDelegateTypes [vtableIndex])); }