コード例 #1
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         * 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);
            }
        }
コード例 #2
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         * 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);
        }
コード例 #3
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         * Emits IL to load the VTable object onto the stack.
         */
        protected virtual void EmitLoadVTable(CppTypeInfo typeInfo)
        {
            var il = typeInfo.emit_info.current_il;

            // this._typeInfo.VTable
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);
            il.Emit(OpCodes.Callvirt, typeinfo_vtable);
        }
コード例 #4
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        protected virtual void EmitResetVTable(CppTypeInfo typeInfo, LocalBuilder cppip)
        {
            var il = typeInfo.emit_info.current_il;

            // this._typeInfo.VTable.ResetInstance (cppInstancePtr);
            EmitLoadVTable(typeInfo);
            il.Emit(OpCodes.Ldloc_S, cppip);
            EmitCallVTableMethod(typeInfo, vtable_resetinstance, 2, false);
        }
コード例 #5
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         * 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);
        }
コード例 #6
0
ファイル: VTable.cs プロジェクト: kthompson/cxxi
        // Subclasses should allocate vtPtr and then call WriteOverrides
        public VTable(CppTypeInfo typeInfo)
        {
            this.initialized = false;
            this.type_info   = typeInfo;
            this.vtPtr       = Marshal.AllocHGlobal((EntryCount * EntrySize) + typeInfo.VTableTopPadding + typeInfo.VTableBottomPadding);

            WriteOverrides();
            CppInstancePtr.RegisterManagedVTable(this);
        }
コード例 #7
0
ファイル: ItaniumAbi.cs プロジェクト: ctguxp/cxxi
		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;
		}
コード例 #8
0
ファイル: MsvcTypeInfo.cs プロジェクト: shana/cppinterop
        // AFIK, MSVC places only its first base's virtual methods in the derived class's
        //  primary vtable. Subsequent base classes (each?) get another vtable pointer
        public override void AddBase(CppTypeInfo baseType)
        {
            if (TypeComplete)
                return;

            if (BaseClasses.Count == 0)
                base.AddBase (baseType, false);
            else
                base.AddBase (baseType, true);
        }
コード例 #9
0
ファイル: ItaniumAbi.cs プロジェクト: ctguxp/cxxi
		internal override Delegate GetManagedOverrideTrampoline (CppTypeInfo typeInfo, int vtableIndex)
		{

			// FIXME: HACK! we really need to support by val return types for managed override trampolines
			if (typeInfo.VirtualMethods [vtableIndex] != null &&
				IsByVal (typeInfo.VirtualMethods [vtableIndex].OrigMethod.ReturnTypeCustomAttributes))
				return null;

			return base.GetManagedOverrideTrampoline (typeInfo, vtableIndex);
		}
コード例 #10
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        // Expects cppip = CppInstancePtr local
        protected virtual void EmitCreateCppObjectFromNative(ILGenerator il, Type targetType, LocalBuilder cppip)
        {
            CppTypeInfo targetTypeInfo = null;

            if (targetType == typeof(ICppObject))
            {
                targetType = typeof(CppInstancePtr);
            }

            // check for a native constructor (i.e. a public ctor in the wrapper that takes CppInstancePtr)
            if (typeof(ICppObject).IsAssignableFrom(targetType))
            {
                var ctor = targetType.GetConstructor(BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance, null, new Type [] { typeof(CppInstancePtr) }, null);
                if (ctor == null)
                {
                    throw new InvalidProgramException(string.Format("Type `{0}' implements ICppObject but does not contain a public constructor that takes CppInstancePtr", targetType));
                }

                // Basically emitting this:
                // CppInstancePtr.ToManaged<targetType> (native) ?? new targetType (native)
                // ..but ToManaged is only called if there's a vtable (FIXME: otherwise we rewrap)

                var hasWrapper = il.DefineLabel();

                if (targetTypeInfo == null)
                {
                    targetTypeInfo = GetTypeInfo(targetType);                      // FIXME: woof. do we really have to do this?
                }
                if (targetTypeInfo != null && targetTypeInfo.HasVTable)
                {
                    il.Emit(OpCodes.Ldloca, cppip);
                    il.Emit(OpCodes.Call, cppip_native);
                    il.Emit(OpCodes.Call, cppip_tomanaged.MakeGenericMethod(targetType));
                    il.Emit(OpCodes.Dup);
                    il.Emit(OpCodes.Brtrue_S, hasWrapper);
                    il.Emit(OpCodes.Pop);
                }

                il.Emit(OpCodes.Ldloc, cppip);
                il.Emit(OpCodes.Newobj, ctor);

                il.MarkLabel(hasWrapper);
            }
            else if (targetType.IsValueType)
            {
                // (targetType)Marshal.PtrToStructure (CppInstancePtr.Native, typeof (targetType))
                il.Emit(OpCodes.Ldloca, cppip);
                il.Emit(OpCodes.Call, cppip_native);
                il.Emit(OpCodes.Ldtoken, targetType);
                il.Emit(OpCodes.Call, type_gettypefromhandle);
                il.Emit(OpCodes.Call, marshal_ptrtostructure);
                il.Emit(OpCodes.Unbox_Any, targetType);
            }
        }
コード例 #11
0
        internal override Delegate GetManagedOverrideTrampoline(CppTypeInfo typeInfo, int vtableIndex)
        {
            // FIXME: HACK! we really need to support by val return types for managed override trampolines
            if (typeInfo.VirtualMethods [vtableIndex] != null &&
                IsByVal(typeInfo.VirtualMethods [vtableIndex].OrigMethod.ReturnTypeCustomAttributes))
            {
                return(null);
            }

            return(base.GetManagedOverrideTrampoline(typeInfo, vtableIndex));
        }
コード例 #12
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);
        }
コード例 #13
0
ファイル: ItaniumAbi.cs プロジェクト: zhoulihe1981/cxxi
        public override PInvokeSignature GetPInvokeSignature(CppTypeInfo /*?*/ typeInfo, MethodInfo method)
        {
            var psig = base.GetPInvokeSignature(typeInfo, method);

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

            return(psig);
        }
コード例 #14
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		// These methods might be more commonly overridden for a given C++ ABI:

		public virtual MethodType GetMethodType (CppTypeInfo typeInfo, MethodInfo imethod)
		{
			if (IsInline (imethod) && !IsVirtual (imethod) && typeInfo.Library.InlineMethodPolicy == InlineMethods.NotPresent)
				return MethodType.NotImplemented;
			else if (imethod.IsDefined (typeof (ConstructorAttribute), false))
				return MethodType.NativeCtor;
			else if (imethod.Name.Equals ("Alloc"))
				return MethodType.ManagedAlloc;
			else if (imethod.IsDefined (typeof (DestructorAttribute), false))
				return MethodType.NativeDtor;

			return MethodType.Native;
		}
コード例 #15
0
ファイル: ItaniumAbi.cs プロジェクト: kthompson/cxxi
        public override IEnumerable<PInvokeSignature> GetVirtualMethodSlots(CppTypeInfo typeInfo, Type interfaceType)
        {
            foreach (var method in base.GetVirtualMethodSlots (typeInfo, interfaceType)) {
                if (!IsVirtual (method.OrigMethod))
                    continue;

                yield return method;

                // Itanium has extra slot for virt dtor
                if (method.Type == MethodType.NativeDtor)
                    yield return null;
            }
        }
コード例 #16
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         * Emits the IL to load the correct delegate instance and/or retrieve the MethodInfo from the VTable
         * for a C++ virtual call.
         */
        protected virtual MethodInfo EmitPrepareVirtualCall(CppTypeInfo typeInfo, LocalBuilder cppInstancePtr, int vtableIndex)
        {
            var il = typeInfo.emit_info.current_il;
            var vtableDelegateType = typeInfo.VTableDelegateTypes [vtableIndex];
            var getDelegate        = typeinfo_adjvcall.MakeGenericMethod(vtableDelegateType);

            // this._typeInfo.GetAdjustedVirtualCall<T> (cppInstancePtr, vtableIndex);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);
            il.Emit(OpCodes.Ldloc_S, cppInstancePtr);
            il.Emit(OpCodes.Ldc_I4, vtableIndex);
            il.Emit(OpCodes.Callvirt, getDelegate);

            return(ReflectionHelper.GetMethodInfoForDelegate(vtableDelegateType));
        }
コード例 #17
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        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);
        }
コード例 #18
0
        public override IEnumerable <PInvokeSignature> GetVirtualMethodSlots(CppTypeInfo typeInfo, Type interfaceType)
        {
            foreach (var method in base.GetVirtualMethodSlots(typeInfo, interfaceType))
            {
                if (!IsVirtual(method.OrigMethod))
                {
                    continue;
                }

                yield return(method);

                // Itanium has extra slot for virt dtor
                if (method.Type == MethodType.NativeDtor)
                {
                    yield return(null);
                }
            }
        }
コード例 #19
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        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");
            }
        }
コード例 #20
0
ファイル: ItaniumAbi.cs プロジェクト: zhoulihe1981/cxxi
        // Section 3.1.4:
        // Classes with non-default copy ctors/destructors are returned using a hidden
        // argument
        bool ReturnByHiddenArgument(CppTypeInfo typeInfo, MethodInfo method)
        {
            var iti = (ItaniumTypeInfo)typeInfo;

            if (!IsByVal(method.ReturnTypeCustomAttributes))
            {
                return(false);
            }

            if (iti.has_non_default_copy_ctor_or_dtor == null)
            {
                iti.has_non_default_copy_ctor_or_dtor = GetMethods(typeInfo.InterfaceType)
                                                        .Any(m => (IsCopyConstructor(m) ||
                                                                   GetMethodType(typeInfo, m) == MethodType.NativeDtor) &&
                                                             !IsArtificial(m));
            }

            return(iti.has_non_default_copy_ctor_or_dtor.Value);
        }
コード例 #21
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        public virtual ICppClass ImplementClass(CppTypeInfo typeInfo)
        {
            if (typeInfo.WrapperType == null || !wrapper_to_typeinfo.ContainsKey(typeInfo.WrapperType))
            {
                if (typeInfo.WrapperType != null)
                {
                    wrapper_to_typeinfo.Add(typeInfo.WrapperType, typeInfo);
                }

                DefineImplType(typeInfo);

                var properties = GetProperties(typeInfo.InterfaceType);
                var methods    = GetMethods(typeInfo.InterfaceType).Select(m => GetPInvokeSignature(typeInfo, m));

                // Implement all methods
                int vtableIndex = 0;
                foreach (var method in methods)
                {
                    DefineMethod(typeInfo, method, ref vtableIndex);
                }

                // Implement all properties
                foreach (var property in properties)
                {
                    DefineProperty(typeInfo, property);
                }

                typeInfo.emit_info.ctor_il.Emit(OpCodes.Ret);

                var native_vtable = default(IntPtr);

#if INIT_NATIVE_VTABLES
                var vtable_symbol = GetMangledVTableName(typeInfo);
                if (vtable_symbol != null)
                {
                    native_vtable = SymbolResolver.ResolveSymbol(SymbolResolver.LoadImage(ref typeInfo.Library.name), vtable_symbol);
                }
#endif
                return((ICppClass)Activator.CreateInstance(typeInfo.emit_info.type_builder.CreateType(), typeInfo, native_vtable));
            }

            throw new InvalidOperationException("This type has already been implemented");
        }
コード例 #22
0
ファイル: ItaniumAbi.cs プロジェクト: zhoulihe1981/cxxi
        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);
                }
            }
        }
コード例 #23
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        // These methods might be more commonly overridden for a given C++ ABI:

        public virtual MethodType GetMethodType(CppTypeInfo typeInfo, MethodInfo imethod)
        {
            if (IsInline(imethod) && !IsVirtual(imethod) && typeInfo.Library.InlineMethodPolicy == InlineMethods.NotPresent)
            {
                return(MethodType.NotImplemented);
            }
            else if (imethod.IsDefined(typeof(ConstructorAttribute), false))
            {
                return(MethodType.NativeCtor);
            }
            else if (imethod.Name.Equals("Alloc"))
            {
                return(MethodType.ManagedAlloc);
            }
            else if (imethod.IsDefined(typeof(DestructorAttribute), false))
            {
                return(MethodType.NativeDtor);
            }

            return(MethodType.Native);
        }
コード例 #24
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        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));
            }

            return(new PInvokeSignature {
                OrigMethod = method,
                Name = GetMangledMethodName(typeInfo, method),
                Type = methodType,
                CallingConvention = GetCallingConvention(method),
                ParameterTypes = pinvokeTypes,
                ReturnType = methodType == MethodType.NativeCtor? typeof(void) :
                             ToPInvokeType(method.ReturnType, method.ReturnTypeCustomAttributes)
            });
        }
コード例 #25
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         * A utility function to emit the IL for a vtable-dependant operation.
         * In other words, classes with no virtual methods will not have vtables,
         * so this method emits code to check for that and either throw an exception
         * or do nothing if no vtable exists. To use, push the arguments to the method you
         * want to call and pass the stackHeight for the call. If no vtable exists, this method
         * will emit code to pop the arguments off the stack.
         */
        protected virtual void EmitCallVTableMethod(CppTypeInfo typeInfo, MethodInfo method, int stackHeight, bool throwOnNoVTable)
        {
            var il = typeInfo.emit_info.current_il;

            // prepare a jump; do not call vtable method if no vtable
            var noVirt          = il.DefineLabel();
            var dontPushOrThrow = il.DefineLabel();

            EmitLoadVTable(typeInfo);
            il.Emit(OpCodes.Brfalse_S, noVirt);             // if (vtableInfo == null) goto noVirt

            il.Emit(OpCodes.Callvirt, method);              // call method
            il.Emit(OpCodes.Br_S, dontPushOrThrow);         // goto dontPushOrThrow

            il.MarkLabel(noVirt);
            // noVirt:
            // since there is no vtable, we did not make the method call.
            // pop arguments
            for (int i = 0; i < stackHeight; i++)
            {
                il.Emit(OpCodes.Pop);
            }

            // if the method was supposed to return a value, we must
            // still push something onto the stack
            // FIXME: This is a kludge. What about value types?
            if (!method.ReturnType.Equals(typeof(void)))
            {
                il.Emit(OpCodes.Ldnull);
            }

            if (throwOnNoVTable)
            {
                il.Emit(OpCodes.Ldstr, "Native class has no VTable.");
                il.Emit(OpCodes.Newobj, typeof(InvalidOperationException).GetConstructor(new Type[] { typeof(string) }));
                il.Emit(OpCodes.Throw);
            }

            il.MarkLabel(dontPushOrThrow);
        }
コード例 #26
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        /**
         *  Emits IL to allocate the memory for a new instance of the C++ class.
         *  To complete method, emit OpCodes.Ret.
         */
        protected virtual void EmitManagedAlloc(CppTypeInfo typeInfo, MethodInfo interfaceMethod)
        {
            var il    = typeInfo.emit_info.current_il;
            var cppip = il.DeclareLocal(typeof(CppInstancePtr));

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);

            if (typeInfo.WrapperType != null && interfaceMethod.GetParameters().Any())
            {
                // load managed wrapper
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Newobj, cppip_fromtype_managed);
            }
            else
            {
                il.Emit(OpCodes.Callvirt, typeinfo_nativesize);
                il.Emit(OpCodes.Newobj, cppip_fromsize);
            }
            il.Emit(OpCodes.Stloc, cppip);

            var unknown_native_vtable = il.DefineLabel();

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, typeInfo.emit_info.native_vtable_field);
            il.Emit(OpCodes.Brfalse_S, unknown_native_vtable);

            il.Emit(OpCodes.Ldloca, cppip);
            il.Emit(OpCodes.Call, cppip_native);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, typeInfo.emit_info.native_vtable_field);
            il.Emit(OpCodes.Call, marshal_writeintptr);

            il.MarkLabel(unknown_native_vtable);
            il.Emit(OpCodes.Ldloc, cppip);
        }
コード例 #27
0
ファイル: CppAbi.cs プロジェクト: zhoulihe1981/cxxi
        protected virtual void DefineImplType(CppTypeInfo typeInfo)
        {
            string implTypeName = typeInfo.InterfaceType.Name + "_";

            if (typeInfo.NativeLayout != null)
            {
                implTypeName += typeInfo.NativeLayout.Name + "_";
            }
            implTypeName += this.GetType().Name + "_Impl";

            var impl_type = CppLibrary.interopModule.DefineType(implTypeName, TypeAttributes.Class | TypeAttributes.Sealed);

            impl_type.AddInterfaceImplementation(typeInfo.InterfaceType);

            var typeinfo_field      = impl_type.DefineField("_typeInfo", typeof(CppTypeInfo), FieldAttributes.InitOnly | FieldAttributes.Private);
            var native_vtable_field = impl_type.DefineField("_nativeVTable", typeof(IntPtr), FieldAttributes.InitOnly | FieldAttributes.Private);

            ConstructorBuilder ctor = impl_type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,
                                                                  new Type[] { typeof(CppTypeInfo), typeof(IntPtr) });

            var ctor_il = ctor.GetILGenerator();

            // this._typeInfo = (CppTypeInfo passed to constructor)
            ctor_il.Emit(OpCodes.Ldarg_0);
            ctor_il.Emit(OpCodes.Ldarg_1);
            ctor_il.Emit(OpCodes.Stfld, typeinfo_field);

            // this._nativeVTable = (vtable ptr passed to constructor)
            ctor_il.Emit(OpCodes.Ldarg_0);
            ctor_il.Emit(OpCodes.Ldarg_2);
            ctor_il.Emit(OpCodes.Stfld, native_vtable_field);

            typeInfo.emit_info.ctor_il             = ctor_il;
            typeInfo.emit_info.typeinfo_field      = typeinfo_field;
            typeInfo.emit_info.native_vtable_field = native_vtable_field;
            typeInfo.emit_info.type_builder        = impl_type;
        }
コード例 #28
0
        protected override string GetMangledVTableName(CppTypeInfo typeInfo)
        {
            var compressMap = new Dictionary <string, int> ();
            var type        = typeInfo.GetMangleType();
            var nm          = new StringBuilder("_ZTV", 30);

            if (type.Namespaces != null)
            {
                nm.Append('N');
                foreach (var ns in type.Namespaces)
                {
                    nm.Append(GetIdentifier(compressMap, ns));
                }
            }

            nm.Append(GetIdentifier(compressMap, type.ElementTypeName));

            if (type.Namespaces != null)
            {
                nm.Append('E');
            }

            return(nm.ToString());
        }
コード例 #29
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		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));
			}

			return new PInvokeSignature {
				OrigMethod = method,
				Name = GetMangledMethodName (typeInfo, method),
				Type = methodType,
				CallingConvention = GetCallingConvention (method),
				ParameterTypes = pinvokeTypes,
				ReturnType = methodType == MethodType.NativeCtor? typeof (void) :
					ToPInvokeType (method.ReturnType, method.ReturnTypeCustomAttributes)
			};
		}
コード例 #30
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * 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);
		}
コード例 #31
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		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);
		}
コード例 #32
0
        // Takes in an address string which identifies the location of the property value in memory,
        // along with property type information.
        // Outputs a string expression which will evaluate to the precise location with the correct C++ type.
        protected string AdjustPropertyExpressionStringForType(string address_str, string prop_type, string uprop_expr_str, DkmVisualizedExpression context_expr, CppTypeInfo cpp_type_info)
        {
            // Special cases first
            switch (prop_type)
            {
                case Prop.Bool:
                    {
                        // Needs special treatment since can be a single bit field as well as just a regular bool
                        // Get a UBoolProperty context
                        var uboolprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Bool);
                        // Read the byte offset and field mask properties
                        string byte_offset_str = GetBoolPropertyByteOffset(uboolprop_em.Expression, context_expr);
                        string field_mask_str = GetBoolPropertyFieldMask(uboolprop_em.Expression, context_expr);
                        // Format an expression which adds the byte offset onto the address, derefs
                        // and then bitwise ANDs with the field mask.
                        return String.Format("(*({0} + {1}) & {2}) != 0",
                            address_str,
                            byte_offset_str,
                            field_mask_str
                            );
                    }

                case Prop.Byte:
                    {
                        // Enum properties are a bit awkward, since due to the different ways the enums can be declared,
                        // we can't reliably access them by a cast and dereference.
                        // eg. A regular enum type will be considered 64 bits.
                        // So, we need to use uint8 to get at the memory, and then do the cast, or rather conversion,
                        // *after* dereferencing in order to get the correct type.
                        return String.Format("({0})*({1}*){2}{3}",
                            cpp_type_info.Type,
                            Typ.Byte,
                            address_str,
                            cpp_type_info.Format
                            );
                    }

                default:
                    break;
            }

            // If we got here, we just need to get the corresponding C++ type, then cast the address
            // to it and dereference.
            // [*(type*)address,fmt]
            return String.Format("*({0}*){1}{2}", cpp_type_info.Type, address_str, cpp_type_info.Format);
        }
コード例 #33
0
ファイル: MsvcAbi.cs プロジェクト: ctguxp/cxxi
		protected override string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo)
		{
			var methodName = methodInfo.Name;
			var type = typeInfo.GetMangleType ();
			var className = type.ElementTypeName;

			MethodType methodType = GetMethodType (typeInfo, methodInfo);
			ParameterInfo [] parameters = methodInfo.GetParameters ();

			StringBuilder nm = new StringBuilder ("?", 30);

			if (methodType == MethodType.NativeCtor)
				nm.Append ("?0");
			else if (methodType == MethodType.NativeDtor)
				nm.Append ("?1");
			else
				nm.Append (methodName).Append ('@');

			// FIXME: This has to include not only the name of the immediate containing class,
			//  but also all names of containing classes and namespaces up the hierarchy.
			nm.Append (className).Append ("@@");

			// function modifiers are a matrix of consecutive uppercase letters
			// depending on access type and virtual (far)/static (far)/far modifiers

			// first, access type
			char funcModifier = 'Q'; // (public)
			if (IsProtected (methodInfo))
				funcModifier = 'I';
			else if (IsPrivate (methodInfo)) // (probably don't need this)
				funcModifier = 'A';

			// now, offset based on other modifiers
			if (IsStatic (methodInfo))
				funcModifier += (char)2;
			else if (IsVirtual (methodInfo))
				funcModifier += (char)4;

			nm.Append (funcModifier);

			// FIXME: deal with other storage classes for "this" i.e. the "volatile" in -> int foo () volatile;
			if (!IsStatic (methodInfo)) {
				if (IsConst (methodInfo))
					nm.Append ('B');
				else
					nm.Append ('A');
			}

			switch (GetCallingConvention (methodInfo)) {
			case CallingConvention.Cdecl:
				nm.Append ('A');
				break;
			case CallingConvention.ThisCall:
				nm.Append ('E');
				break;
			case CallingConvention.StdCall:
				nm.Append ('G');
				break;
			case CallingConvention.FastCall:
				nm.Append ('I');
				break;
			}

			// FIXME: handle const, volatile modifiers on return type
			// FIXME: the manual says this is only omitted for simple types.. are we doing the right thing here?
			CppType returnType = GetMangleType (methodInfo.ReturnTypeCustomAttributes, methodInfo.ReturnType);
			if (returnType.ElementType == CppTypes.Class ||
			    returnType.ElementType == CppTypes.Struct ||
			    returnType.ElementType == CppTypes.Union)
				nm.Append ("?A");

			if (methodType == MethodType.NativeCtor || methodType == MethodType.NativeDtor)
				nm.Append ('@');
			else
				nm.Append (GetTypeCode (returnType));

			int argStart = (IsStatic (methodInfo)? 0 : 1);
			if (parameters.Length == argStart) { // no args (other than C++ "this" object)
				nm.Append ("XZ");
				return nm.ToString ();
			} else
				for (int i = argStart; i < parameters.Length; i++)
					nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType)));

			nm.Append ("@Z");
			return nm.ToString ();
		}
コード例 #34
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		// Implementing this is recommended..
		//  otherwise it is not possible to instantiate classes that have vtables and only implicitly defined ctor
		// Return null if not implemented or if the symbol name of the vtable for the passed typeInfo cannot be mangled (i.e. because there's no vtable)
		protected virtual string GetMangledVTableName (CppTypeInfo typeInfo)
		{
			return null;
		}
コード例 #35
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		protected virtual void EmitResetVTable (CppTypeInfo typeInfo, LocalBuilder cppip)
		{
			var il = typeInfo.emit_info.current_il;

			// this._typeInfo.VTable.ResetInstance (cppInstancePtr);
			EmitLoadVTable (typeInfo);
			il.Emit (OpCodes.Ldloc_S, cppip);
			EmitCallVTableMethod (typeInfo, vtable_resetinstance, 2, false);
		}
コード例 #36
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * 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;
		}
コード例 #37
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * 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]);
		}
コード例 #38
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		protected virtual PropertyBuilder DefineProperty (CppTypeInfo typeInfo, PropertyInfo property)
		{
			if (property.CanWrite)
				throw new InvalidProgramException ("Properties in C++ interface must be read-only.");

			var imethod = property.GetGetMethod ();
			var methodName = imethod.Name;
			var propName = property.Name;
			var retType = imethod.ReturnType;

			var fieldProp = typeInfo.emit_info.type_builder.DefineProperty (propName, PropertyAttributes.None, retType, Type.EmptyTypes);

			var methodAttr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
			var fieldGetter = typeInfo.emit_info.type_builder.DefineMethod (methodName, methodAttr, retType, Type.EmptyTypes);
			var il = fieldGetter.GetILGenerator ();

			// C++ interface properties are either to return the CppTypeInfo or to access C++ fields
			if (retType.IsGenericType && retType.GetGenericTypeDefinition ().Equals (typeof (CppField<>))) {

				// define a new field for the property
				var fieldData = typeInfo.emit_info.type_builder.DefineField ("__" + propName + "_Data", retType, FieldAttributes.InitOnly | FieldAttributes.Private);

				// we need to lazy init the field because we don't have accurate field offset until after
				// all base classes have been added (by ctor)
				var lazyInit = il.DefineLabel ();

				il.Emit (OpCodes.Ldarg_0);
				il.Emit (OpCodes.Ldfld, fieldData);
				il.Emit (OpCodes.Dup);
				il.Emit (OpCodes.Brfalse_S, lazyInit);
				il.Emit (OpCodes.Ret);

				// init new CppField
				il.MarkLabel (lazyInit);
				il.Emit (OpCodes.Pop);

				il.Emit (OpCodes.Ldarg_0);

				// first, get field offset
				//  = ((int)Marshal.OffsetOf (layout_type, propName)) + FieldOffsetPadding;
				il.Emit(OpCodes.Ldtoken, typeInfo.NativeLayout);
				il.Emit(OpCodes.Call, type_gettypefromhandle);
				il.Emit(OpCodes.Ldstr, propName);
				il.Emit(OpCodes.Call, marshal_offsetof);

				il.Emit (OpCodes.Ldarg_0);
				il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);
				il.Emit (OpCodes.Callvirt, typeinfo_fieldoffset);

				il.Emit (OpCodes.Add);

				// new CppField<T> (<field offset>)
				il.Emit (OpCodes.Newobj, retType.GetConstructor (new Type[] { typeof(int) }));

				il.Emit (OpCodes.Stfld, fieldData);

				il.Emit (OpCodes.Ldarg_0);
				il.Emit (OpCodes.Ldfld, fieldData);
				il.Emit (OpCodes.Ret);

			} else if (retType.Equals (typeof (CppTypeInfo))) {
				il.Emit (OpCodes.Ldarg_0);
				il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);
				il.Emit (OpCodes.Ret);
			} else
				throw new InvalidProgramException ("Properties in C++ interface can only be of type CppField.");

			fieldProp.SetGetMethod (fieldGetter);

			return fieldProp;
		}
コード例 #39
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		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;
		}
コード例 #40
0
ファイル: ItaniumAbi.cs プロジェクト: kthompson/cxxi
        protected override string GetMangledMethodName(CppTypeInfo typeInfo, MethodInfo methodInfo)
        {
            var compressMap = new Dictionary<string, int> ();
            var methodName = methodInfo.Name;
            var type = typeInfo.GetMangleType ();
            var className = type.ElementTypeName;

            MethodType methodType = GetMethodType (typeInfo, methodInfo);
            ParameterInfo [] parameters = methodInfo.GetParameters ();

            StringBuilder nm = new StringBuilder ("_ZN", 30);

            if (IsConst (methodInfo))
                nm.Append ('K');

            if (type.Namespaces != null) {
                foreach (var ns in type.Namespaces)
                    nm.Append (GetIdentifier (compressMap, ns));
            }

            nm.Append (GetIdentifier (compressMap, className));

            // Insert the class template types here
            var templates = type.Modifiers.OfType<CppModifiers.TemplateModifier>().FirstOrDefault();
            if (templates != null)
            {
                nm.Append("I");
                foreach (var mangleType in templates.Types)
                    nm.Append (GetTypeCode (mangleType, compressMap));
                nm.Append("E");
            }

            // FIXME: Implement compression completely

            switch (methodType) {
            case MethodType.NativeCtor:
                nm.Append ("C1");
                break;

            case MethodType.NativeDtor:
                nm.Append ("D1");
                break;

            default:
                nm.Append (methodName.Length).Append (methodName);
                break;
            }

            nm.Append ('E');
            int argStart = (IsStatic (methodInfo)? 0 : 1);

            if (parameters.Length == argStart) // no args (other than C++ "this" object)
                nm.Append ('v');
            else
                for (int i = argStart; i < parameters.Length; i++)
                    nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType), compressMap));

            return nm.ToString ();
        }
コード例 #41
0
 public sp_u_fdbg_symbol_s(CppTypeInfo subClass)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #42
0
ファイル: ItaniumAbi.cs プロジェクト: kthompson/cxxi
        protected override string GetMangledVTableName(CppTypeInfo typeInfo)
        {
            var compressMap = new Dictionary<string, int> ();
            var type = typeInfo.GetMangleType ();
            var nm = new StringBuilder ("_ZTV", 30);

            if (type.Namespaces != null) {
                    nm.Append ('N');
                    foreach (var ns in type.Namespaces)
                        nm.Append (GetIdentifier (compressMap, ns));
            }

            nm.Append (GetIdentifier (compressMap, type.ElementTypeName));

            if (type.Namespaces != null)
                nm.Append ('E');

            return nm.ToString ();
        }
コード例 #43
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * Emits IL to load the VTable object onto the stack.
		 */
		protected virtual void EmitLoadVTable (CppTypeInfo typeInfo)
		{
			var il = typeInfo.emit_info.current_il;

			// this._typeInfo.VTable
			il.Emit (OpCodes.Ldarg_0);
			il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);
			il.Emit (OpCodes.Callvirt, typeinfo_vtable);
		}
コード例 #44
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * 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;
		}
コード例 #45
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * A utility function to emit the IL for a vtable-dependant operation.
		 * In other words, classes with no virtual methods will not have vtables,
		 * so this method emits code to check for that and either throw an exception
		 * or do nothing if no vtable exists. To use, push the arguments to the method you
		 * want to call and pass the stackHeight for the call. If no vtable exists, this method
		 * will emit code to pop the arguments off the stack.
		 */
		protected virtual void EmitCallVTableMethod (CppTypeInfo typeInfo, MethodInfo method, int stackHeight, bool throwOnNoVTable)
		{
			var il = typeInfo.emit_info.current_il;

			// prepare a jump; do not call vtable method if no vtable
			var noVirt = il.DefineLabel ();
			var dontPushOrThrow = il.DefineLabel ();

			EmitLoadVTable (typeInfo);
			il.Emit (OpCodes.Brfalse_S, noVirt); // if (vtableInfo == null) goto noVirt

			il.Emit (OpCodes.Callvirt, method); // call method
			il.Emit (OpCodes.Br_S, dontPushOrThrow); // goto dontPushOrThrow

			il.MarkLabel (noVirt);
			// noVirt:
			// since there is no vtable, we did not make the method call.
			// pop arguments
			for (int i = 0; i < stackHeight; i++)
				il.Emit (OpCodes.Pop);

			// if the method was supposed to return a value, we must
			// still push something onto the stack
			// FIXME: This is a kludge. What about value types?
			if (!method.ReturnType.Equals (typeof (void)))
				il.Emit (OpCodes.Ldnull);

			if (throwOnNoVTable) {
				il.Emit (OpCodes.Ldstr, "Native class has no VTable.");
				il.Emit (OpCodes.Newobj, typeof (InvalidOperationException).GetConstructor(new Type[] {typeof (string)}));
				il.Emit (OpCodes.Throw);
			}

			il.MarkLabel (dontPushOrThrow);
		}
コード例 #46
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 * Emits the IL to load the correct delegate instance and/or retrieve the MethodInfo from the VTable
		 * for a C++ virtual call.
		 */
		protected virtual MethodInfo EmitPrepareVirtualCall (CppTypeInfo typeInfo, LocalBuilder cppInstancePtr, int vtableIndex)
		{
			var il = typeInfo.emit_info.current_il;
			var vtableDelegateType = typeInfo.VTableDelegateTypes [vtableIndex];
			var getDelegate  = typeinfo_adjvcall.MakeGenericMethod (vtableDelegateType);

			// this._typeInfo.GetAdjustedVirtualCall<T> (cppInstancePtr, vtableIndex);
			il.Emit (OpCodes.Ldarg_0);
			il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);
			il.Emit (OpCodes.Ldloc_S, cppInstancePtr);
			il.Emit (OpCodes.Ldc_I4, vtableIndex);
			il.Emit (OpCodes.Callvirt, getDelegate);

			return ReflectionHelper.GetMethodInfoForDelegate (vtableDelegateType);
		}
コード例 #47
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		/**
		 *  Emits IL to allocate the memory for a new instance of the C++ class.
		 *  To complete method, emit OpCodes.Ret.
		 */
		protected virtual void EmitManagedAlloc (CppTypeInfo typeInfo, MethodInfo interfaceMethod)
		{
			var il = typeInfo.emit_info.current_il;
			var cppip = il.DeclareLocal (typeof (CppInstancePtr));

			il.Emit (OpCodes.Ldarg_0);
			il.Emit (OpCodes.Ldfld, typeInfo.emit_info.typeinfo_field);

			if (typeInfo.WrapperType != null && interfaceMethod.GetParameters ().Any ()) {
				// load managed wrapper
				il.Emit (OpCodes.Ldarg_1);
				il.Emit (OpCodes.Newobj, cppip_fromtype_managed);
			} else {
				il.Emit (OpCodes.Callvirt, typeinfo_nativesize);
				il.Emit (OpCodes.Newobj, cppip_fromsize);
			}
			il.Emit (OpCodes.Stloc, cppip);

			var unknown_native_vtable = il.DefineLabel ();
			il.Emit (OpCodes.Ldarg_0);
			il.Emit (OpCodes.Ldfld, typeInfo.emit_info.native_vtable_field);
			il.Emit (OpCodes.Brfalse_S, unknown_native_vtable);

			il.Emit (OpCodes.Ldloca, cppip);
			il.Emit (OpCodes.Call, cppip_native);

			il.Emit (OpCodes.Ldarg_0);
			il.Emit (OpCodes.Ldfld, typeInfo.emit_info.native_vtable_field);
			il.Emit (OpCodes.Call, marshal_writeintptr);

			il.MarkLabel (unknown_native_vtable);
			il.Emit (OpCodes.Ldloc, cppip);
		}
コード例 #48
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		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");
			}
		}
コード例 #49
0
ファイル: RTPSource.cs プロジェクト: wxmiswxm/rtsp-wrapper
 public RTPSource(CppTypeInfo subClass)
     : base(impl.TypeInfo)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #50
0
 public ICompilation(CppTypeInfo subClass)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #51
0
 public SMInterface(CppTypeInfo subClass)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #52
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		protected abstract string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo);
コード例 #53
0
 public __si_class_type_info_pseudo(CppTypeInfo subClass)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #54
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		public virtual ICppClass ImplementClass (CppTypeInfo typeInfo)
		{
			if (typeInfo.WrapperType == null || !wrapper_to_typeinfo.ContainsKey (typeInfo.WrapperType)) {

				if (typeInfo.WrapperType != null)
					wrapper_to_typeinfo.Add (typeInfo.WrapperType, typeInfo);

				DefineImplType (typeInfo);

				var properties = GetProperties (typeInfo.InterfaceType);
				var methods = GetMethods (typeInfo.InterfaceType).Select (m => GetPInvokeSignature (typeInfo, m));
	
				// Implement all methods
				int vtableIndex = 0;
				foreach (var method in methods)
					DefineMethod (typeInfo, method, ref vtableIndex);

				// Implement all properties
				foreach (var property in properties)
					DefineProperty (typeInfo, property);

				typeInfo.emit_info.ctor_il.Emit (OpCodes.Ret);

				var native_vtable = default (IntPtr);

#if INIT_NATIVE_VTABLES
				var vtable_symbol = GetMangledVTableName (typeInfo);
				if (vtable_symbol != null)
					native_vtable = SymbolResolver.ResolveSymbol (SymbolResolver.LoadImage (ref typeInfo.Library.name), vtable_symbol);
#endif
				return (ICppClass)Activator.CreateInstance (typeInfo.emit_info.type_builder.CreateType (), typeInfo, native_vtable);
			}

			throw new InvalidOperationException ("This type has already been implemented");
		}
コード例 #55
0
 public UsageEnvironment(CppTypeInfo subClass)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #56
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		public virtual IEnumerable<PInvokeSignature> GetVirtualMethodSlots (CppTypeInfo typeInfo, Type interfaceType)
		{
			return from m in GetMethods (interfaceType)
	                where IsVirtual (m)
	                select GetPInvokeSignature (typeInfo, m);
		}
コード例 #57
0
        // Takes in a UE4 property type string (eg. IntPropery, ObjectProperty, etc) along with a
        // expression string which evaluates to a UProperty*, and maps to the corresponding C++ type.
        protected CppTypeInfo[] GetCppTypeForPropertyType(string prop_type, string uprop_expr_str, DkmVisualizedExpression context_expr)
        {
            switch (prop_type)
            {
                case Prop.Bool:
                    return new CppTypeInfo[] {
                        new CppTypeInfo("bool")
                    };

                case Prop.Struct:
                    {
                        // This is gonna be effort.
                        // Get UStructProperty
                        var ustructprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Struct);
                        // Need to access its UScriptStruct* member 'Struct', and get its object name.
                        var struct_name_expr_str = ustructprop_em.PtrMember(Memb.CppStruct).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                        // Get that name string
                        string struct_name = UE4Utility.GetFNameAsString(struct_name_expr_str, context_expr);
                        // Add the 'F' prefix
                        return new CppTypeInfo[] {
                            new CppTypeInfo("F" + struct_name)
                        };
                    }

                case Prop.Byte:
                    {
                        // Could be plain uint8, or a UEnum.
                        // Get UByteProperty
                        var ubyteprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Byte);
                        // Need to access its UEnum* member 'Enum'.
                        var uenum_em = ubyteprop_em.PtrMember(Memb.EnumType);
                        // Evaluate this to see if it is null or not
                        bool is_enum_valid = !UE4Utility.IsPointerNull(uenum_em.Expression, context_expr);
                        if (is_enum_valid)
                        {
                            // This property is an enum, so the type we want is the fully qualified C++ enum type.

                            // @NOTE: Seems that the CppType member should be exactly what we need, but appears to actually be unused.
                            //string cpp_enum_name_expr_str = uenum_em.PtrMember("CppType").Expression;

                            string uenum_fname_expr_str = uenum_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                            string uenum_name = UE4Utility.GetFNameAsString(uenum_fname_expr_str, context_expr);

                            // We need to know if it's a namespaced enum or not
                            string is_namespaced_enum_expr_str = String.Format(
                                "{0}==UEnum::ECppForm::Namespaced",
                                uenum_em.PtrMember(Memb.EnumCppForm).Expression
                                );
                            var is_namespaced_res = UE4Utility.EvaluateBooleanExpression(is_namespaced_enum_expr_str, context_expr);
                            // @TODO: on evaluation failure??
                            CppTypeInfo primary;
                            if (is_namespaced_res.IsValid && is_namespaced_res.Value)
                            {
                                // A namespaced enum type should (hopefully) always be <UEnum::Name>::Type
                                primary = new CppTypeInfo(String.Format("{0}::Type", uenum_name), uenum_name);
                            }
                            else
                            {
                                // For regular or enum class enums, the full type name should be just the name of the UEnum object.
                                primary = new CppTypeInfo(uenum_name);
                            }

                            return new CppTypeInfo[] {
                                primary,
                                // Fallback onto regular byte display, in case enum name symbol not available
                                new CppTypeInfo(Typ.Byte, uenum_name + "?")
                            };
                        }
                        else
                        {
                            // Must just be a regular uint8
                            return new CppTypeInfo[] {
                                new CppTypeInfo(Typ.Byte)
                            };
                        }
                    }

                case Prop.Array:
                    {
                        // Okay, cast to UArrayProperty and get the inner property type
                        var array_prop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Array);
                        var inner_prop_em = array_prop_em.PtrMember(Memb.ArrayInner);

                        // @TODO: Need to look into how TArray< bool > is handled.
                        string inner_prop_type = GetPropertyType(inner_prop_em.Expression, context_expr);
                        var inner_cpp_type_info = GetCppTypeForPropertyType(inner_prop_type, inner_prop_em.Expression, context_expr);

                        var result = new CppTypeInfo[inner_cpp_type_info.Length];
                        for (int i = 0; i < inner_cpp_type_info.Length; ++i)
                        {
                            // Type needed is TArray< %inner_cpp_type%, FDefaultAllocator >
                            string type = String.Format("{0}<{1},{2}>", Typ.Array, inner_cpp_type_info[i].Type, Typ.DefaultAlloc);
                            // Omit allocator from display string, since for UPROPERTY arrays it can't be anything else
                            string display = String.Format("{0}<{1}>", Typ.Array, inner_cpp_type_info[i].Display);
                            result[i] = new CppTypeInfo(type, display);
                        }
                        return result;
                    }

                case Prop.Object:
                case Prop.Asset:
                    {
                        if(!Config.ShowExactUObjectTypes)
                        {
                            break;
                        }

                        string obj_cpp_type_name = Typ.UObject;

                        // Need to find out the subtype of the property, which is specified by UObjectPropertyBase::PropertyClass
                        var objprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.ObjectBase);
                        var subtype_uclass_em = objprop_em.PtrMember(Memb.ObjectSubtype);
                        var uclass_fname_em = subtype_uclass_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName);
                        string uclass_fname = UE4Utility.GetFNameAsString(uclass_fname_em.Expression, context_expr);

                        // Is the property class native?
                        var is_native_res = UE4Utility.IsNativeUClassOrUInterface(subtype_uclass_em.Expression, context_expr);
                        // @TODO: currently not really handling failed eval
                        bool is_native = is_native_res.IsValid ? is_native_res.Value : true;
                        string native_uclass_fname;
                        if (is_native)
                        {
                            // Yes
                            native_uclass_fname = uclass_fname;
                        }
                        else
                        {
                            // No, we need to retrieve the name of its native base
                            native_uclass_fname = UE4Utility.GetBlueprintClassNativeBaseName(subtype_uclass_em.Expression, context_expr);
                        }

                        Debug.Assert(native_uclass_fname != null);

                        // Now we have to convert the unprefixed name, to a prefixed C++ type name
                        obj_cpp_type_name = UE4Utility.DetermineNativeUClassCppTypeName(native_uclass_fname, context_expr);

                        string uclass_display_name = UE4Utility.GetBlueprintClassDisplayName(uclass_fname);
                        switch (prop_type)
                        {
                            case Prop.Object:
                                {
                                    // if not native, add a suffix to the display type showing the blueprint class of the property
                                    // @NOTE: this is nothing to do with what object the value points to and what its type may be. property meta data only.
                                    string suffix = is_native ? String.Empty : String.Format(" [{0}]", uclass_display_name);
                                    string primary_type = String.Format("{0} *", obj_cpp_type_name);
                                    string primary_display = String.Format("{0} *{1}", obj_cpp_type_name, suffix);
                                    // fallback, no symbols available for the native base type, so use 'UObject' instead
                                    string fallback_type = String.Format("{0} *", Typ.UObject);
                                    string fallback_display = String.Format("{0}? *{1}", obj_cpp_type_name, suffix);

                                    return new CppTypeInfo[]
                                    {
                                        new CppTypeInfo(primary_type, primary_display),
                                        new CppTypeInfo(fallback_type, fallback_display)
                                    };
                                }

                            case Prop.Asset:
                                {
                                    // @NOTE: Don't really see anything to gain by casting to TAssetPtr< xxx >, since it's just another level of encapsulation that isn't
                                    // needed for visualization purposes.
                                    string suffix = String.Format(" [{0}]", is_native ? obj_cpp_type_name : uclass_display_name);
                                    string primary_type = Typ.AssetPtr; //String.Format("TAssetPtr<{0}>", obj_cpp_type_name);
                                    string primary_display = String.Format("{0}{1}", Typ.AssetPtr, suffix);

                                    // If just using FAssetPtr, no need for a fallback since we don't need to evaluate the specialized template parameter type
                                    return new CppTypeInfo[]
                                    {
                                        new CppTypeInfo(primary_type, primary_display)
                                    };
                                }

                            default:
                                Debug.Assert(false);
                                return null;
                        }
                    }

            /*				@TODO: Not so important. What's below is wrong, but essentially if we implement this, it's just to differentiate between UClass, UBlueprintGeneratedClass, etc
                case "ClassProperty":
                case "AssetClassProperty":
                    {
                        if (!Config.ShowExactUObjectTypes)
                        {
                            break;
                        }

                        // Need to find out the subtype of the property, which is specified by UClassProperty::MetaClass/UAssetClassProperty::MetaClass
                        // Cast to whichever property type we are (either UClassProperty or UAssetClassProperty)
                        string propclass_name = String.Format("U{0}", prop_type);
                        var classprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(propclass_name);
                        // Either way, we have a member called 'MetaClass' which specified the base UClass stored in this property
                        var subtype_uclass_em = classprop_em.PtrMember("MetaClass");
                        var subtype_fname_em = subtype_uclass_em.PtrCast("UObjectBase").PtrMember("Name");
                        string subtype_fname = UE4Utility.GetFNameAsString(subtype_fname_em.Expression, context_expr);
                        return String.Format("U{0}*", subtype_fname);
                    }
            */			}

            // Standard cases, just use cpp type stored in map.
            // If not found, null string will be returned.
            string cpp_type = null;
            if (ue4_proptype_map_.TryGetValue(prop_type, out cpp_type))
            {
                return new CppTypeInfo[] { new CppTypeInfo(cpp_type) };
            }
            else
            {
                return null;
            }
        }
コード例 #58
0
ファイル: CppAbi.cs プロジェクト: ctguxp/cxxi
		protected virtual void DefineImplType (CppTypeInfo typeInfo)
		{
			string implTypeName = typeInfo.InterfaceType.Name + "_";
			if (typeInfo.NativeLayout != null)
				implTypeName += typeInfo.NativeLayout.Name + "_";
			implTypeName += this.GetType ().Name + "_Impl";

			var impl_type = CppLibrary.interopModule.DefineType (implTypeName, TypeAttributes.Class | TypeAttributes.Sealed);
			impl_type.AddInterfaceImplementation (typeInfo.InterfaceType);

			var typeinfo_field = impl_type.DefineField ("_typeInfo", typeof (CppTypeInfo), FieldAttributes.InitOnly | FieldAttributes.Private);
			var native_vtable_field = impl_type.DefineField ("_nativeVTable", typeof (IntPtr), FieldAttributes.InitOnly | FieldAttributes.Private);

			ConstructorBuilder ctor = impl_type.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard,
                                                                              new Type[] { typeof (CppTypeInfo), typeof (IntPtr) });

			var ctor_il = ctor.GetILGenerator ();

			// this._typeInfo = (CppTypeInfo passed to constructor)
			ctor_il.Emit (OpCodes.Ldarg_0);
			ctor_il.Emit (OpCodes.Ldarg_1);
			ctor_il.Emit (OpCodes.Stfld, typeinfo_field);

			// this._nativeVTable = (vtable ptr passed to constructor)
			ctor_il.Emit (OpCodes.Ldarg_0);
			ctor_il.Emit (OpCodes.Ldarg_2);
			ctor_il.Emit (OpCodes.Stfld, native_vtable_field);

			typeInfo.emit_info.ctor_il = ctor_il;
			typeInfo.emit_info.typeinfo_field = typeinfo_field;
			typeInfo.emit_info.native_vtable_field = native_vtable_field;
			typeInfo.emit_info.type_builder = impl_type;
		}
コード例 #59
0
 public sp_fdbg_ntvtab_s(CppTypeInfo subClass)
 {
     __cxxi_LayoutClass();
     subClass.AddBase(impl.TypeInfo);
 }
コード例 #60
0
ファイル: ItaniumAbi.cs プロジェクト: ctguxp/cxxi
		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);
				}
			}
		}