Пример #1
0
        public static Type CreateWrapper <T>(IntPtr Instance, out NativeClassInfo NativeCInfo) where T : class
        {
            NativeCInfo = null;

            string WrapperName = typeof(T).Name + "_impl";

            if (NativeClassWrappers.ContainsKey(WrapperName))
            {
                return(NativeClassWrappers[WrapperName]);
            }

            NativeClassInfo NativeInfo = NativeCInfo = NativeClass.CalculateClassLayout(typeof(T));

            Type TypeWrapper = CreateInterfaceImpl <T>(WrapperName, (TB) => {
                foreach (var VarInf in NativeInfo.VariableInfo)
                {
                    CreateVariableImpl(TB, VarInf.PropertyInfo, VarInf.Offset);
                }

                foreach (var MetInf in NativeInfo.MethodInfo)
                {
                    if (MetInf.DoesOverride)
                    {
                        continue;
                    }

                    CreateMethodImpl(TB, MetInf.Method, (MB, ILGen, ParamTypes) => {
                        ILGen.Emit(OpCodes.Ldarg_0);
                        ILGen.Emit(OpCodes.Ldc_I4, MetInf.ThisOffset);
                        ILGen.EmitCall(OpCodes.Call, TB.BaseType.GetMethod(nameof(NativeClassImpl.OffsetThisPtr)), null);

                        for (int i = 0; i < ParamTypes.Length; i++)
                        {
                            ILGen.Emit(OpCodes.Ldarg, i + 1);
                        }

                        ILGen.Emit(OpCodes.Ldarg_0);
                        ILGen.Emit(OpCodes.Ldc_I4, MetInf.VTableOffset);
                        ILGen.Emit(OpCodes.Ldc_I4, MetInf.MethodIndex);
                        ILGen.EmitCall(OpCodes.Call, TB.BaseType.GetMethod(nameof(NativeClassImpl.GetMethodPointer)), null);

                        ILGen.EmitCalli(OpCodes.Calli, CallingConvention.ThisCall, MetInf.Method.ReturnType, new Type[] { typeof(IntPtr) }.Append(ParamTypes));
                        ILGen.Emit(OpCodes.Ret);
                    });
                }
            });


            NativeClassWrappers.Add(WrapperName, TypeWrapper);
            return(TypeWrapper);
        }
Пример #2
0
        public static NativeClassInfo CalculateClassLayout(Type T)
        {
            List <NativeMethodInfo>   MethodInfos   = new List <NativeMethodInfo>();
            List <NativeVariableInfo> VariableInfos = new List <NativeVariableInfo>();

            Dictionary <int, int> MethodCounter   = new Dictionary <int, int>();
            Dictionary <int, int> VariableOffsets = new Dictionary <int, int>();

            CalculateVTableLayout(T, (VTableOffset, Interface) => {
                MethodInfo[] Methods = Interface.GetMethods();

                if (!MethodCounter.ContainsKey(VTableOffset))
                {
                    MethodCounter.Add(VTableOffset, 0);
                    VariableOffsets.Add(VTableOffset, VTablePointerSize);
                }

                for (int i = 0; i < Methods.Length; i++)
                {
                    PropertyInfo Prop;
                    if ((Prop = GetPropertyForMethod(Methods[i])) != null)
                    {
                        if (Prop.GetSetMethod() == Methods[i])
                        {
                            continue;
                        }

                        NativeVariableInfo VarInfo = new NativeVariableInfo();
                        VarInfo.Offset             = VariableOffsets[VTableOffset];

                        VarInfo.PropertyInfo = Prop;
                        VarInfo.VariableType = VarInfo.PropertyInfo.PropertyType;
                        VarInfo.Name         = VarInfo.PropertyInfo.Name;

                        VariableOffsets[VTableOffset] += Marshal.SizeOf(VarInfo.VariableType);
                        VariableInfos.Add(VarInfo);
                        continue;
                    }

                    NativeMethodInfo VMethInfo = new NativeMethodInfo();
                    VMethInfo.Method           = Methods[i];

                    MethodInfo BMI;
                    if (BaseContains(Methods[i], out BMI))
                    {
                        VMethInfo.BaseMethod   = BMI;
                        VMethInfo.DoesOverride = true;
                    }
                    else
                    {
                        VMethInfo.BaseMethod   = null;
                        VMethInfo.MethodIndex  = MethodCounter[VTableOffset]++;
                        VMethInfo.VTableOffset = VTableOffset;
                        VMethInfo.DoesOverride = false;
                    }

                    MethodInfos.Add(VMethInfo);
                }
            });

            NativeClassInfo Ret = new NativeClassInfo();

            Ret.MethodInfo.AddRange(MethodInfos);
            Ret.VariableInfo.AddRange(VariableInfos);
            return(Ret);
        }