Exemplo n.º 1
0
        private static Type CreateDelegateTypeForNativeFunctionSignature(NativeFunctionSignature functionSignature, string functionName)
        {
            if (_customDelegateTypesModule == null)
            {
                var aName = new AssemblyName("HelperRuntimeDelegates");
                var delegateTypesAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave);
                _customDelegateTypesModule = delegateTypesAssembly.DefineDynamicModule(aName.Name, aName.Name + ".dll");
            }

            var delBuilder = _customDelegateTypesModule.DefineType("HelperNativeDelegate" + _createdDelegateTypes.ToString(),
                                                                   TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass, typeof(MulticastDelegate));

            //ufp = UnmanagedFunctionPointer
            object[]    ufpAttrCtorArgValues = { functionSignature.callingConvention };
            FieldInfo[] ufpAttrNamedFields   = { Field_Ufpa_BestFitMapping.Value, Field_Ufpa_CharSet.Value, Field_Ufpa_SetLastError.Value, Field_Ufpa_ThrowOnUnmappableChar.Value };
            object[]    ufpAttrFieldValues   = { functionSignature.bestFitMapping, functionSignature.charSet, functionSignature.setLastError, functionSignature.throwOnUnmappableChar };
            var         ufpAttrBuilder       = new CustomAttributeBuilder(Ctor_Ufp.Value, ufpAttrCtorArgValues, ufpAttrNamedFields, ufpAttrFieldValues);

            delBuilder.SetCustomAttribute(ufpAttrBuilder);

            var ctorBuilder = delBuilder.DefineConstructor(MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
                                                           CallingConventions.Standard, DELEGATE_CTOR_PARAMETERS);

            ctorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);

            var invokeBuilder = delBuilder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot,
                                                        CallingConventions.Standard | CallingConventions.HasThis, functionSignature.returnParameter.type, functionSignature.parameters.Select(p => p.type).ToArray());

            invokeBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
            var invokeReturnParam = invokeBuilder.DefineParameter(0, functionSignature.returnParameter.parameterAttributes, null);

            foreach (var attr in functionSignature.returnParameter.customAttributes)
            {
                var attrBuilder = CreateAttributeBuilderFromAttributeInstance(attr, functionName);
                if (attrBuilder != null)
                {
                    invokeReturnParam.SetCustomAttribute(attrBuilder);
                }
            }
            for (int i = 0; i < functionSignature.parameters.Length; i++)
            {
                var param        = functionSignature.parameters[i];
                var paramBuilder = invokeBuilder.DefineParameter(i + 1, param.parameterAttributes, null);
                foreach (var attr in param.customAttributes)
                {
                    var attrBuilder = CreateAttributeBuilderFromAttributeInstance(attr, functionName);
                    if (attrBuilder != null)
                    {
                        paramBuilder.SetCustomAttribute(attrBuilder);
                    }
                }
            }

            _createdDelegateTypes++;
            return(delBuilder.CreateType());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates and registers new DynamicMethod that mocks <paramref name="nativeMethod"/> and itself calls dynamically loaded function from DLL.
        /// </summary>
        private static DynamicMethod GetNativeFunctionMockMethod(MethodInfo nativeMethod)
        {
            if (!_nativeFunctionMocks.TryGetValue(nativeMethod, out var mockedDynamicMethod))
            {
                var    dllImportAttr = nativeMethod.GetCustomAttribute <DllImportAttribute>();
                var    dllName       = dllImportAttr.Value;
                string dllPath;
                var    nativeFunctionSymbol = dllImportAttr.EntryPoint;

                if (_dlls.TryGetValue(dllName, out var dll))
                {
                    dllPath = dll.path;
                }
                else
                {
                    dllPath = ApplyDirectoryPathMacros(Options.dllPathPattern).Replace(DLL_PATH_PATTERN_DLL_NAME_MACRO, dllName);
                    dll     = new NativeDll(dllName, dllPath);
                    _dlls.Add(dllName, dll);
                }

                var nativeFunction = new NativeFunction(nativeFunctionSymbol, dll);
                dll.functions.Add(nativeFunction);
                var nativeFunctionIndex = _mockedNativeFunctions.Count;
                _mockedNativeFunctions.Add(nativeFunction);

                var parameters            = nativeMethod.GetParameters();
                var parameterTypes        = parameters.Select(x => x.ParameterType).ToArray();
                var nativeMethodSignature = new NativeFunctionSignature(nativeMethod, dllImportAttr.CallingConvention,
                                                                        dllImportAttr.BestFitMapping, dllImportAttr.CharSet, dllImportAttr.SetLastError, dllImportAttr.ThrowOnUnmappableChar);
                if (!_delegateTypesForNativeFunctionSignatures.TryGetValue(nativeMethodSignature, out nativeFunction.delegateType))
                {
                    nativeFunction.delegateType = CreateDelegateTypeForNativeFunctionSignature(nativeMethodSignature, nativeMethod.Name);
                    _delegateTypesForNativeFunctionSignatures.Add(nativeMethodSignature, nativeFunction.delegateType);
                }
                var targetDelegateInvokeMethod = nativeFunction.delegateType.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public);

                mockedDynamicMethod = new DynamicMethod(dllName + ":::" + nativeFunctionSymbol, nativeMethod.ReturnType, parameterTypes, typeof(DllManipulator));
                mockedDynamicMethod.DefineParameter(0, nativeMethod.ReturnParameter.Attributes, null);
                for (int i = 0; i < parameters.Length; i++)
                {
                    mockedDynamicMethod.DefineParameter(i + 1, parameters[i].Attributes, null);
                }

                GenerateNativeFunctionMockBody(mockedDynamicMethod.GetILGenerator(), parameters, targetDelegateInvokeMethod, nativeFunctionIndex);

                _antiGcRefHolder.AddLast(nativeFunction);
                _antiGcRefHolder.AddLast(mockedDynamicMethod);
            }

            return(mockedDynamicMethod);
        }