Beispiel #1
0
        /**
         * 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);
        }
Beispiel #2
0
        /**
         * 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);
        }
Beispiel #3
0
        /**
         * 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]));
        }