Example #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);
        }
Example #2
0
		protected override MethodBuilder DefineMethod (CppTypeInfo typeInfo, PInvokeSignature sig, ref int vtableIndex)
		{
			var builder = base.DefineMethod (typeInfo, sig, ref vtableIndex);

			// increment vtableIndex an extra time for that extra vdtor slot (already incremented once in base)
			if (IsVirtual (sig.OrigMethod) && sig.Type == MethodType.NativeDtor)
				vtableIndex++;

			return builder;
		}
Example #3
0
        protected override MethodBuilder DefineMethod(CppTypeInfo typeInfo, PInvokeSignature sig, ref int vtableIndex)
        {
            var builder = base.DefineMethod(typeInfo, sig, ref vtableIndex);

            // increment vtableIndex an extra time for that extra vdtor slot (already incremented once in base)
            if (IsVirtual(sig.OrigMethod) && sig.Type == MethodType.NativeDtor)
            {
                vtableIndex++;
            }

            return(builder);
        }
Example #4
0
/*
		protected override void AddBase (CppTypeInfo baseType, BaseVirtualMethods location)
		{
			if (TypeComplete)
				return;

			// When adding a non-primary base class's complete vtable, we need to reserve space for
			// the stuff before the address point of the vtptr..
			// Includes vbase & vcall offsets (virtual inheritance), offset to top, and RTTI info
			if (addVTable) {

				// FIXME: virtual inheritance
				virtual_methods.Add (null);
				virtual_methods.Add (null);

				vt_overrides.Add (2);
				vt_delegate_types.Add (2);
			}

			base.AddBase (baseType, addVTable);
		}
*/
		protected override bool OnVTableDuplicate (ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup)
		{
			var isOverride = base.OnVTableDuplicate (ref iter, ref adj, sig, dup);
			if (isOverride && sig.Type == MethodType.NativeDtor) {

				// also remove that pesky extra dtor
				virtual_methods.RemoveAt (iter + 1);
				vt_overrides.Remove (1);
				vt_delegate_types.Remove (1);
				vtable_index_adjustments.Add (0);
				adj--;
				return true;
			}

			return false;
		}
Example #5
0
        protected virtual bool OnVTableDuplicate(ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup)
        {
            // This predicate ensures that duplicates are only removed
            // if declared in different classes (i.e. overridden methods).
            // We usually want to allow the same exact virtual methods to appear
            // multiple times, in the case of nonvirtual diamond inheritance, for example.
            if (!sig.OrigMethod.Equals(dup.OrigMethod))
            {
                virtual_methods.RemoveAt(iter--);
                vt_overrides.Remove(1);
                vt_delegate_types.Remove(1);
                adj--;
                return(true);
            }

            return(false);
        }
Example #6
0
/*
 *              protected override void AddBase (CppTypeInfo baseType, BaseVirtualMethods location)
 *              {
 *                      if (TypeComplete)
 *                              return;
 *
 *                      // When adding a non-primary base class's complete vtable, we need to reserve space for
 *                      // the stuff before the address point of the vtptr..
 *                      // Includes vbase & vcall offsets (virtual inheritance), offset to top, and RTTI info
 *                      if (addVTable) {
 *
 *                              // FIXME: virtual inheritance
 *                              virtual_methods.Add (null);
 *                              virtual_methods.Add (null);
 *
 *                              vt_overrides.Add (2);
 *                              vt_delegate_types.Add (2);
 *                      }
 *
 *                      base.AddBase (baseType, addVTable);
 *              }
 */
        protected override bool OnVTableDuplicate(ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup)
        {
            var isOverride = base.OnVTableDuplicate(ref iter, ref adj, sig, dup);

            if (isOverride && sig.Type == MethodType.NativeDtor)
            {
                // also remove that pesky extra dtor
                virtual_methods.RemoveAt(iter + 1);
                vt_overrides.Remove(1);
                vt_delegate_types.Remove(1);
                vtable_index_adjustments.Add(0);
                adj--;
                return(true);
            }

            return(false);
        }
Example #7
0
		/**
		 * Emits IL to call the native method. nativeMethod should be either a method obtained by
		 * GetPInvokeForMethod or the MethodInfo of a vtable method.
		 * To complete method, emit OpCodes.Ret.
		 */
		protected virtual void EmitNativeCall (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr)
		{
			var il = typeInfo.emit_info.current_il;
			var interfaceMethod = psig.OrigMethod;
			var interfaceArgs = interfaceMethod.GetParameters ();

			int argLoadStart = 1; // For static methods, just strip off arg0 (.net this pointer)
			if (!IsStatic (interfaceMethod))
			{
				argLoadStart = 2; // For instance methods, strip off CppInstancePtr and pass the corresponding IntPtr
				il.Emit (OpCodes.Ldloc_S, nativePtr);
			}

			// load and marshal arguments
			for (int i = argLoadStart; i <= interfaceArgs.Length; i++) {
				il.Emit (OpCodes.Ldarg, i);
				EmitOutboundMarshal (il, interfaceArgs [i - 1].ParameterType, psig.ParameterTypes [i - 1]);
			}

			il.Emit (OpCodes.Call, nativeMethod);

			// Marshal return value
			if (psig.Type != MethodType.NativeCtor)
				EmitInboundMarshal (il, psig.ReturnType, interfaceMethod.ReturnType);
		}
Example #8
0
        protected virtual void EmitDestruct(CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig,
                                            LocalBuilder cppInstancePtr, LocalBuilder nativePtr)
        {
            Debug.Assert(psig.Type == MethodType.NativeDtor);
            var il = typeInfo.emit_info.current_il;

            // we don't do anything if the object wasn't managed alloc
            if (cppInstancePtr == null)
            {
                return;
            }

            EmitCheckManagedAlloc(il, cppInstancePtr);

            EmitResetVTable(typeInfo, cppInstancePtr);
            EmitNativeCall(typeInfo, nativeMethod, psig, nativePtr);
        }
Example #9
0
		protected virtual void EmitConstruct (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig,
		                                      LocalBuilder cppInstancePtr, LocalBuilder nativePtr)
		{
			Debug.Assert (psig.Type == MethodType.NativeCtor);
			var il = typeInfo.emit_info.current_il;

			EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr);

			if (cppInstancePtr != null && psig.OrigMethod.ReturnType == typeof (CppInstancePtr)) {
				EmitInitVTable (typeInfo, cppInstancePtr);
				il.Emit (OpCodes.Ldloc_S, cppInstancePtr);

			} else if (psig.OrigMethod.DeclaringType.GetInterfaces ().Any (i => i.IsGenericType && i.GetGenericTypeDefinition () == typeof (ICppClassOverridable<>))) {
				throw new InvalidProgramException ("In ICppClassOverridable, native constructors must take as first argument and return CppInstancePtr");
			}
		}
Example #10
0
		protected virtual void EmitDestruct (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig,
		                                     LocalBuilder cppInstancePtr, LocalBuilder nativePtr)
		{
			Debug.Assert (psig.Type == MethodType.NativeDtor);
			var il = typeInfo.emit_info.current_il;

			// we don't do anything if the object wasn't managed alloc
			if (cppInstancePtr == null)
				return;

			EmitCheckManagedAlloc (il, cppInstancePtr);

			EmitResetVTable (typeInfo, cppInstancePtr);
			EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr);
		}
Example #11
0
		protected virtual MethodBuilder DefineMethod (CppTypeInfo typeInfo, PInvokeSignature psig, ref int vtableIndex)
		{
			var interfaceMethod = psig.OrigMethod;

			// 1. Generate managed trampoline to call native method
			var trampoline = GetMethodBuilder (typeInfo, interfaceMethod);
			var il = typeInfo.emit_info.current_il = trampoline.GetILGenerator ();

			switch (psig.Type) {

			case MethodType.NotImplemented:
				il.Emit (OpCodes.Ldstr, "This method is not available.");
				il.Emit (OpCodes.Newobj, notimplementedexception);
				il.Emit (OpCodes.Throw);

				goto case MethodType.NoOp; // fallthrough
			case MethodType.NoOp:
				// return NULL if method is supposed to return a value
				if (!interfaceMethod.ReturnType.Equals (typeof (void)))
					il.Emit (OpCodes.Ldnull);
				il.Emit (OpCodes.Ret);
				return trampoline;

			case MethodType.ManagedAlloc:
				EmitManagedAlloc (typeInfo, interfaceMethod);
				il.Emit (OpCodes.Ret);
				return trampoline;
			}

			var isStatic = IsStatic (interfaceMethod);
			LocalBuilder cppInstancePtr = null;
			LocalBuilder nativePtr = null;

			// If we're an instance method, load up the "this" pointer
			if (!isStatic)
			{
				if (psig.ParameterTypes.Count == 0)
					throw new ArgumentException ("First argument to non-static C++ method must be instance pointer.");

				// 2. Load the native C++ instance pointer
				EmitLoadInstancePtr (il, interfaceMethod.GetParameters () [0].ParameterType, out cppInstancePtr, out nativePtr);

				// 3. Make sure our native pointer is a valid reference. If not, throw ObjectDisposedException
				EmitCheckDisposed (il, nativePtr, psig.Type);
			}

			MethodInfo nativeMethod;

			if (IsVirtual (interfaceMethod) && psig.Type != MethodType.NativeDtor) {
				nativeMethod = EmitPrepareVirtualCall (typeInfo, cppInstancePtr, vtableIndex++);
			} else {
				if (IsVirtual (interfaceMethod))
					vtableIndex++;

				nativeMethod = GetPInvokeForMethod (typeInfo, psig);
			}

			switch (psig.Type) {
			case MethodType.NativeCtor:
				EmitConstruct (typeInfo, nativeMethod, psig, cppInstancePtr, nativePtr);
				break;
			case MethodType.NativeDtor:
				EmitDestruct (typeInfo, nativeMethod, psig, cppInstancePtr, nativePtr);
				break;
			default:
				EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr);
				break;
			}

			il.Emit (OpCodes.Ret);
			return trampoline;
		}
Example #12
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;
		}
Example #13
0
        protected override void EmitNativeCall(CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr)
        {
            var il                  = typeInfo.emit_info.current_il;
            var method              = psig.OrigMethod;
            var returnType          = method.ReturnType;
            var hiddenReturnByValue = ReturnByHiddenArgument(typeInfo, method);

            LocalBuilder returnValue = null;

            if (hiddenReturnByValue)
            {
                returnValue = il.DeclareLocal(typeof(CppInstancePtr));

                if (typeof(ICppObject).IsAssignableFrom(returnType))
                {
                    il.Emit(OpCodes.Ldc_I4, GetTypeInfo(returnType).NativeSize);
                }
                else if (returnType.IsValueType)
                {
                    il.Emit(OpCodes.Ldc_I4, Marshal.SizeOf(returnType));
                }

                il.Emit(OpCodes.Newobj, cppip_fromsize);
                il.Emit(OpCodes.Stloc, returnValue);
                il.Emit(OpCodes.Ldloca, returnValue);
                il.Emit(OpCodes.Call, cppip_native);
            }

            base.EmitNativeCall(typeInfo, nativeMethod, psig, nativePtr);

            if (hiddenReturnByValue)
            {
                EmitCreateCppObjectFromNative(il, returnType, returnValue);

                if (returnType.IsValueType)
                {
                    // FIXME: This dispose should prolly be in a Finally block..
                    il.Emit(OpCodes.Ldloca, returnValue);
                    il.Emit(OpCodes.Call, cppip_dispose);
                }
            }
        }
Example #14
0
        /**
         * Emits IL to call the native method. nativeMethod should be either a method obtained by
         * GetPInvokeForMethod or the MethodInfo of a vtable method.
         * To complete method, emit OpCodes.Ret.
         */
        protected virtual void EmitNativeCall(CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr)
        {
            var il = typeInfo.emit_info.current_il;
            var interfaceMethod = psig.OrigMethod;
            var interfaceArgs = interfaceMethod.GetParameters ();
            var returnType = interfaceMethod.ReturnType;
            var hiddenReturnByValue = ReturnByHiddenArgument (typeInfo, interfaceMethod);

            LocalBuilder returnValue = null;

            if (hiddenReturnByValue) {
                returnValue = il.DeclareLocal (typeof (CppInstancePtr));

                if (typeof (ICppObject).IsAssignableFrom (returnType))
                    il.Emit (OpCodes.Ldc_I4, GetTypeInfo (returnType).NativeSize);
                else if (returnType.IsValueType)
                    il.Emit (OpCodes.Ldc_I4, Marshal.SizeOf (returnType));

                il.Emit (OpCodes.Newobj, cppip_fromsize);
                il.Emit (OpCodes.Stloc, returnValue);
                il.Emit (OpCodes.Ldloca, returnValue);
                il.Emit (OpCodes.Call, cppip_native);
            }

            int argLoadStart = 1; // For static methods, just strip off arg0 (.net this pointer)
            if (!this.IsStatic (interfaceMethod)) {
                argLoadStart = 2; // For instance methods, strip off CppInstancePtr and pass the corresponding IntPtr
                il.Emit (OpCodes.Ldloc_S, nativePtr);
            }

            // load and marshal arguments
            for (int i = argLoadStart; i <= interfaceArgs.Length; i++) {
                il.Emit (OpCodes.Ldarg, i);
                this.EmitOutboundMarshal (il, interfaceArgs[i - 1].ParameterType, psig.ParameterTypes[i - 1]);
            }

            il.Emit (OpCodes.Call, nativeMethod);

            // Marshal return value
            if (psig.Type != MethodType.NativeCtor)
                this.EmitInboundMarshal (il, psig.ReturnType, interfaceMethod.ReturnType);

            if (hiddenReturnByValue) {
                EmitCreateCppObjectFromNative (il, returnType, returnValue);

                if (returnType.IsValueType) {
                    // FIXME: This dispose should prolly be in a Finally block..
                    il.Emit (OpCodes.Ldloca, returnValue);
                    il.Emit (OpCodes.Call, cppip_dispose);
                }
            }
        }
Example #15
0
		protected override void EmitNativeCall (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr)
		{
			var il = typeInfo.emit_info.current_il;
			var method = psig.OrigMethod;
			var returnType = method.ReturnType;
			var hiddenReturnByValue = ReturnByHiddenArgument (typeInfo, method);

			LocalBuilder returnValue = null;

			if (hiddenReturnByValue)
			{
				returnValue = il.DeclareLocal (typeof (CppInstancePtr));

				if (typeof (ICppObject).IsAssignableFrom (returnType))
					il.Emit (OpCodes.Ldc_I4, GetTypeInfo (returnType).NativeSize);
				else if (returnType.IsValueType)
					il.Emit (OpCodes.Ldc_I4, Marshal.SizeOf (returnType));

				il.Emit (OpCodes.Newobj, cppip_fromsize);
				il.Emit (OpCodes.Stloc, returnValue);
				il.Emit (OpCodes.Ldloca, returnValue);
				il.Emit (OpCodes.Call, cppip_native);
			}

			base.EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr);

			if (hiddenReturnByValue) {
				EmitCreateCppObjectFromNative (il, returnType, returnValue);

				if (returnType.IsValueType) {
					// FIXME: This dispose should prolly be in a Finally block..
					il.Emit (OpCodes.Ldloca, returnValue);
					il.Emit (OpCodes.Call, cppip_dispose);
				}
			}
		}
Example #16
0
        protected virtual void EmitConstruct(CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig,
                                             LocalBuilder cppInstancePtr, LocalBuilder nativePtr)
        {
            Debug.Assert(psig.Type == MethodType.NativeCtor);
            var il = typeInfo.emit_info.current_il;

            EmitNativeCall(typeInfo, nativeMethod, psig, nativePtr);

            if (cppInstancePtr != null && psig.OrigMethod.ReturnType == typeof(CppInstancePtr))
            {
                EmitInitVTable(typeInfo, cppInstancePtr);
                il.Emit(OpCodes.Ldloc_S, cppInstancePtr);
            }
            else if (psig.OrigMethod.DeclaringType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICppClassOverridable <>)))
            {
                throw new InvalidProgramException("In ICppClassOverridable, native constructors must take as first argument and return CppInstancePtr");
            }
        }
Example #17
0
        protected virtual MethodBuilder DefineMethod(CppTypeInfo typeInfo, PInvokeSignature psig, ref int vtableIndex)
        {
            var interfaceMethod = psig.OrigMethod;

            // 1. Generate managed trampoline to call native method
            var trampoline = GetMethodBuilder(typeInfo, interfaceMethod);
            var il         = typeInfo.emit_info.current_il = trampoline.GetILGenerator();

            switch (psig.Type)
            {
            case MethodType.NotImplemented:
                il.Emit(OpCodes.Ldstr, "This method is not available.");
                il.Emit(OpCodes.Newobj, notimplementedexception);
                il.Emit(OpCodes.Throw);

                goto case MethodType.NoOp;                 // fallthrough

            case MethodType.NoOp:
                // return NULL if method is supposed to return a value
                if (!interfaceMethod.ReturnType.Equals(typeof(void)))
                {
                    il.Emit(OpCodes.Ldnull);
                }
                il.Emit(OpCodes.Ret);
                return(trampoline);

            case MethodType.ManagedAlloc:
                EmitManagedAlloc(typeInfo, interfaceMethod);
                il.Emit(OpCodes.Ret);
                return(trampoline);
            }

            var          isStatic       = IsStatic(interfaceMethod);
            LocalBuilder cppInstancePtr = null;
            LocalBuilder nativePtr      = null;

            // If we're an instance method, load up the "this" pointer
            if (!isStatic)
            {
                if (psig.ParameterTypes.Count == 0)
                {
                    throw new ArgumentException("First argument to non-static C++ method must be instance pointer.");
                }

                // 2. Load the native C++ instance pointer
                EmitLoadInstancePtr(il, interfaceMethod.GetParameters() [0].ParameterType, out cppInstancePtr, out nativePtr);

                // 3. Make sure our native pointer is a valid reference. If not, throw ObjectDisposedException
                EmitCheckDisposed(il, nativePtr, psig.Type);
            }

            MethodInfo nativeMethod;

            if (IsVirtual(interfaceMethod) && psig.Type != MethodType.NativeDtor)
            {
                nativeMethod = EmitPrepareVirtualCall(typeInfo, cppInstancePtr, vtableIndex++);
            }
            else
            {
                if (IsVirtual(interfaceMethod))
                {
                    vtableIndex++;
                }

                nativeMethod = GetPInvokeForMethod(typeInfo, psig);
            }

            switch (psig.Type)
            {
            case MethodType.NativeCtor:
                EmitConstruct(typeInfo, nativeMethod, psig, cppInstancePtr, nativePtr);
                break;

            case MethodType.NativeDtor:
                EmitDestruct(typeInfo, nativeMethod, psig, cppInstancePtr, nativePtr);
                break;

            default:
                EmitNativeCall(typeInfo, nativeMethod, psig, nativePtr);
                break;
            }

            il.Emit(OpCodes.Ret);
            return(trampoline);
        }
Example #18
0
        /**
         * Emits IL to call the native method. nativeMethod should be either a method obtained by
         * GetPInvokeForMethod or the MethodInfo of a vtable method.
         * To complete method, emit OpCodes.Ret.
         */
        protected virtual void EmitNativeCall(CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr)
        {
            var il = typeInfo.emit_info.current_il;
            var interfaceMethod = psig.OrigMethod;
            var interfaceArgs   = interfaceMethod.GetParameters();

            int argLoadStart = 1;             // For static methods, just strip off arg0 (.net this pointer)

            if (!IsStatic(interfaceMethod))
            {
                argLoadStart = 2;                 // For instance methods, strip off CppInstancePtr and pass the corresponding IntPtr
                il.Emit(OpCodes.Ldloc_S, nativePtr);
            }

            // load and marshal arguments
            for (int i = argLoadStart; i <= interfaceArgs.Length; i++)
            {
                il.Emit(OpCodes.Ldarg, i);
                EmitOutboundMarshal(il, interfaceArgs [i - 1].ParameterType, psig.ParameterTypes [i - 1]);
            }

            il.Emit(OpCodes.Call, nativeMethod);

            // Marshal return value
            if (psig.Type != MethodType.NativeCtor)
            {
                EmitInboundMarshal(il, psig.ReturnType, interfaceMethod.ReturnType);
            }
        }
Example #19
0
        public virtual PInvokeSignature GetPInvokeSignature(CppTypeInfo typeInfo, MethodInfo method)
        {
            var methodType = GetMethodType (typeInfo, method);
            var parameters = method.GetParameters ();
            var pinvokeTypes = new List<Type> (parameters.Length);

            foreach (var pi in parameters) {
                pinvokeTypes.Add (ToPInvokeType (pi.ParameterType, pi));
            }

            Type returnType = method.ReturnType;
            if (methodType == MethodType.NativeCtor)
                returnType = typeof(void);
            else if (method.ReturnTypeCustomAttributes.IsDefined(typeof(ByRefAttribute), false))
                returnType = typeof(IntPtr);
            else
                returnType = ToPInvokeType (method.ReturnType, method.ReturnTypeCustomAttributes);

            var psig = new PInvokeSignature {
                OrigMethod = method,
                Name = GetMangledMethodName (typeInfo, method),
                Type = methodType,
                CallingConvention = GetCallingConvention (method),
                ParameterTypes = pinvokeTypes,
                ReturnType = returnType
            };

            if (ReturnByHiddenArgument (typeInfo, method)) {
                psig.ParameterTypes.Insert (0, typeof (IntPtr));
                psig.ReturnType = typeof (void);
            }

            return psig;
        }