示例#1
0
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var newParameterTypes = definition.ParameterTypes.Select(t => t.IsNonRefNullable() ? typeof(IntPtr) : t).ToArray();
            var newReturnType     = definition.ReturnType.IsNonRefNullable() ? typeof(IntPtr) : definition.ReturnType;

            var passthroughMethod = TargetType.DefineMethod
                                    (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                newReturnType,
                newParameterTypes
                                    );

            // Copy over all the attributes, except MarshalAsAttributes to IntPtr parameters
            passthroughMethod.ApplyCustomAttributesFrom
            (
                definition,
                newReturnType,
                newParameterTypes
            );

            return(new IntrospectiveMethodInfo(passthroughMethod, newReturnType, newParameterTypes, definition));
        }
示例#2
0
        /// <inheritdoc/>
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition
        (
            PipelineWorkUnit <IntrospectiveMethodInfo> workUnit
        )
        {
            var definition = workUnit.Definition;

            var newReturnType     = GetParameterPassthroughType(definition.ReturnType);
            var newParameterTypes = definition.ParameterTypes.Select(GetParameterPassthroughType).ToArray();

            var passthroughMethod = TargetType.DefineMethod
                                    (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                newParameterTypes
                                    );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, newParameterTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       newParameterTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
示例#3
0
        /// <inheritdoc />
        public override IEnumerable <PipelineWorkUnit <IntrospectiveMethodInfo> > GenerateImplementation(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var permutations = new List <IntrospectiveMethodInfo>();
            var definition   = workUnit.Definition;

            // Generate permutation definitions
            var parameterPermutations = _permutationGenerator.Generate(definition);

            for (int i = 0; i < parameterPermutations.Count; ++i)
            {
                var permutation = parameterPermutations[i];
                var method      = TargetType.DefineMethod
                                  (
                    $"{workUnit.GetUniqueBaseMemberName()}_permutation_{i}",
                    Public | Final | Virtual | HideBySig | NewSlot,
                    CallingConventions.Standard,
                    definition.ReturnType,
                    permutation.ToArray()
                                  );

                var methodInfo = new IntrospectiveMethodInfo(method, definition.ReturnType, permutation, definition);
                permutations.Add(methodInfo);
            }

            GenerateTopLevelMethodImplementation(definition, permutations);

            // Pass the permutations on for further processing
            foreach (var permutation in permutations)
            {
                yield return(new PipelineWorkUnit <IntrospectiveMethodInfo>(permutation, workUnit));
            }
        }
示例#4
0
        protected MethodBuilder GenerateSymbolLoadingLambda([NotNull] string symbolName)
        {
            var uniqueIdentifier = Guid.NewGuid().ToString().Replace("-", "_");

            var loadSymbolMethod = typeof(NativeLibraryBase).GetMethod
                                   (
                "LoadSymbol",
                BindingFlags.NonPublic | BindingFlags.Instance
                                   );

            // Generate lambda loader
            var lambdaBuilder = TargetType.DefineMethod
                                (
                $"{symbolName}_{uniqueIdentifier}_lazy",
                Private | HideBySig | Final,
                typeof(IntPtr),
                null
                                );

            var lambdaIL = lambdaBuilder.GetILGenerator();

            lambdaIL.Emit(OpCodes.Ldarg_0);
            lambdaIL.Emit(OpCodes.Ldstr, symbolName);
            lambdaIL.Emit(OpCodes.Call, loadSymbolMethod);
            lambdaIL.Emit(OpCodes.Ret);
            return(lambdaBuilder);
        }
示例#5
0
        private IntrospectiveMethodInfo GenerateLoweredMethodDefinition
        (
            [NotNull] IntrospectiveMethodInfo complexInterfaceMethod,
            [NotNull] string memberIdentifier
        )
        {
            var newReturnType = LowerTypeIfRequired(complexInterfaceMethod.ReturnType);

            var newParameterTypes = new List <Type>();

            foreach (var parameterType in complexInterfaceMethod.ParameterTypes)
            {
                newParameterTypes.Add(LowerTypeIfRequired(parameterType));
            }

            var loweredMethodBuilder = TargetType.DefineMethod
                                       (
                $"{memberIdentifier}_lowered",
                Public | Final | Virtual | HideBySig | NewSlot,
                CallingConventions.Standard,
                newReturnType,
                newParameterTypes.ToArray()
                                       );

            return(new IntrospectiveMethodInfo(loweredMethodBuilder, newReturnType, newParameterTypes, complexInterfaceMethod));
        }
        protected MethodBuilder GenerateFunctionLoadingLambda([NotNull] Type delegateType, [NotNull] string functionName)
        {
            var uniqueIdentifier = Guid.NewGuid().ToString().Replace('-', '_');

            var loadFuncMethod = typeof(NativeLibraryBase).GetMethod
                                 (
                nameof(NativeLibraryBase.LoadFunction),
                BindingFlags.NonPublic | BindingFlags.Instance
                                 );

            // ReSharper disable once PossibleNullReferenceException
            var loadFunc = loadFuncMethod.MakeGenericMethod(delegateType);

            // Generate lambda loader
            var lambdaBuilder = TargetType.DefineMethod
                                (
                $"{delegateType.Name}_{uniqueIdentifier}_lazy",
                Private | HideBySig | Final,
                delegateType,
                null
                                );

            var lambdaIL = lambdaBuilder.GetILGenerator();

            lambdaIL.EmitLoadArgument(0);
            lambdaIL.EmitConstantString(functionName);
            lambdaIL.EmitCallDirect(loadFunc);
            lambdaIL.EmitReturn();

            return(lambdaBuilder);
        }
示例#7
0
        protected MethodBuilder GenerateFunctionLoadingLambda([NotNull] Type delegateType, [NotNull] string functionName)
        {
            var uniqueIdentifier = Guid.NewGuid().ToString().Replace("-", "_");

            var loadFuncMethod = typeof(NativeLibraryBase).GetMethod
                                 (
                "LoadFunction",
                BindingFlags.NonPublic | BindingFlags.Instance
                                 );

            var loadFunc = loadFuncMethod.MakeGenericMethod(delegateType);

            // Generate lambda loader
            var lambdaBuilder = TargetType.DefineMethod
                                (
                $"{delegateType.Name}_{uniqueIdentifier}_lazy",
                Private | HideBySig | Final,
                delegateType,
                null
                                );

            var lambdaIL = lambdaBuilder.GetILGenerator();

            lambdaIL.Emit(OpCodes.Ldarg_0);
            lambdaIL.Emit(OpCodes.Ldstr, functionName);
            lambdaIL.Emit(OpCodes.Call, loadFunc);
            lambdaIL.Emit(OpCodes.Ret);
            return(lambdaBuilder);
        }
        protected MethodBuilder GenerateSymbolLoadingLambda([NotNull] string symbolName)
        {
            var uniqueIdentifier = Guid.NewGuid().ToString().Replace('-', '_');

            var loadSymbolMethod = typeof(NativeLibraryBase).GetMethod
                                   (
                nameof(NativeLibraryBase.LoadSymbol),
                BindingFlags.NonPublic | BindingFlags.Instance
                                   );

            // Generate lambda loader
            var lambdaBuilder = TargetType.DefineMethod
                                (
                $"{symbolName}_{uniqueIdentifier}_lazy",
                Private | HideBySig | Final,
                typeof(IntPtr),
                null
                                );

            var lambdaIL = lambdaBuilder.GetILGenerator();

            lambdaIL.EmitLoadArgument(0);
            lambdaIL.EmitConstantString(symbolName);
            lambdaIL.EmitCallDirect(loadSymbolMethod);
            lambdaIL.EmitReturn();

            return(lambdaBuilder);
        }
示例#9
0
        /// <inheritdoc />
        protected override void GenerateImplementation(IntrospectiveMethodInfo member, string symbolName, string uniqueMemberIdentifier)
        {
            var generatedMethods = new List <IntrospectiveMethodInfo>();

            // Generate permutation definitions
            var permutations = _permutationGenerator.Generate(member);

            for (int i = 0; i < permutations.Count; ++i)
            {
                var permutation = permutations[i];
                var method      = TargetType.DefineMethod
                                  (
                    $"{uniqueMemberIdentifier}_{i}",
                    Public | Final | Virtual | HideBySig | NewSlot,
                    CallingConventions.Standard,
                    member.ReturnType,
                    permutation.ToArray()
                                  );

                var methodInfo = new IntrospectiveMethodInfo(method, member.ReturnType, permutation, member);
                generatedMethods.Add(methodInfo);
            }

            // Generate native implementations for the permutations
            foreach (var permutation in generatedMethods)
            {
                var uniqueIdentifier = Guid.NewGuid().ToString().Replace("-", "_");
                var memberIdentifier = $"{member.Name}_{uniqueIdentifier}";

                uniqueMemberIdentifier = memberIdentifier;

                if (permutation.RequiresLowering())
                {
                    _loweredMethodGenerator.GenerateImplementationForDefinition(permutation, symbolName, uniqueMemberIdentifier);
                }
                else
                {
                    _methodGenerator.GenerateImplementationForDefinition(permutation, symbolName, uniqueMemberIdentifier);
                }
            }

            // Generate a definition for the top-level method
            var topLevelMethod = TargetType.DefineMethod
                                 (
                symbolName,
                Public | Final | Virtual | HideBySig | NewSlot,
                member.ReturnType,
                member.ParameterTypes.ToArray()
                                 );

            GenerateTopLevelMethodImplementation(member, topLevelMethod, permutations, generatedMethods);
            TargetType.DefineMethodOverride(topLevelMethod, member.GetWrappedMember());
        }
示例#10
0
        private IntrospectiveMethodInfo GenerateInvokerDefinition([NotNull] IntrospectiveMethodInfo methodDefinition)
        {
            var methodBuilder = TargetType.DefineMethod
                                (
                methodDefinition.Name,
                Public | Final | Virtual | HideBySig | NewSlot,
                Standard,
                methodDefinition.ReturnType,
                methodDefinition.ParameterTypes.ToArray()
                                );

            return(new IntrospectiveMethodInfo(methodBuilder, methodDefinition.ReturnType, methodDefinition.ParameterTypes, methodDefinition));
        }
        /// <summary>
        /// Generates the definition of the complex method.
        /// </summary>
        /// <param name="interfaceDefinition">The interface definition to base it on.</param>
        /// <returns>An introspective method info for the definition.</returns>
        private IntrospectiveMethodInfo GenerateComplexMethodDefinition([NotNull] IntrospectiveMethodInfo interfaceDefinition)
        {
            var methodBuilder = TargetType.DefineMethod
                                (
                interfaceDefinition.Name,
                Public | Final | Virtual | HideBySig | NewSlot,
                CallingConventions.Standard,
                interfaceDefinition.ReturnType,
                interfaceDefinition.ParameterTypes.ToArray()
                                );

            return(new IntrospectiveMethodInfo(methodBuilder, interfaceDefinition.ReturnType, interfaceDefinition.ParameterTypes, interfaceDefinition));
        }
        public virtual IntrospectiveMethodInfo GeneratePassthroughDefinition([NotNull] PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var passthroughMethod = TargetType.DefineMethod
                                    (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapper",
                Private | Virtual | HideBySig,
                CallingConventions.Standard,
                definition.ReturnType,
                definition.ParameterTypes.ToArray()
                                    );

            passthroughMethod.ApplyCustomAttributesFrom(workUnit.Definition);

            return(new IntrospectiveMethodInfo(passthroughMethod, definition.ReturnType, definition.ParameterTypes, definition));
        }
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            if (!workUnit.Definition.ReturnType.GenericTypeArguments[0].IsValueType)
            {
                // Span<byte> is used because unbound generics are not allowed inside a nameof, and it still results as just 'Span'
                throw new NotSupportedException($"Method is not a {nameof(ValueType)} and cannot be marshaled as a {nameof(Span<byte>)}. Marshalling {nameof(Span<byte>)}" +
                                                $"requires the marshaled type T in {nameof(Span<byte>)}<T> to be a {nameof(ValueType)}");
            }

            var definition = workUnit.Definition;

            Type newReturnType = definition.ReturnType.GenericTypeArguments[0].MakePointerType();

            /* TODO? Add marshaling for Span<> params */

            Type[] parametersTypes = definition.ParameterTypes.ToArray();

            MethodBuilder passthroughMethod = TargetType.DefineMethod
                                              (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                parametersTypes
                                              );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, parametersTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       parametersTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
示例#14
0
        private void GeneratePropertyGetter
        (
            [NotNull] IntrospectivePropertyInfo property,
            [NotNull] FieldInfo propertyFieldBuilder,
            [NotNull] PropertyBuilder propertyBuilder
        )
        {
            var wrappedProperty = property.GetWrappedMember();
            var actualGetMethod = wrappedProperty.GetGetMethod();
            var getterMethod    = TargetType.DefineMethod
                                  (
                actualGetMethod.Name,
                PropertyMethodAttributes,
                actualGetMethod.CallingConvention,
                actualGetMethod.ReturnType,
                Type.EmptyTypes
                                  );

            MethodInfo underlyingMethod;

            if (property.PropertyType.IsPointer)
            {
                underlyingMethod = typeof(Marshal).GetMethods().First
                                   (
                    m =>
                    m.Name == nameof(Marshal.ReadIntPtr) &&
                    m.GetParameters().Length == 1
                                   );
            }
            else if (property.PropertyType.IsValueType)
            {
                underlyingMethod = typeof(Marshal).GetMethods().First
                                   (
                    m =>
                    m.Name == nameof(Marshal.PtrToStructure) &&
                    m.GetParameters().Length == 1 &&
                    m.IsGenericMethod
                                   )
                                   .MakeGenericMethod(property.PropertyType);
            }
            else
            {
                throw new NotSupportedException
                      (
                          $"The type \"{property.PropertyType.FullName}\" is not supported. Only value types or pointers are supported."
                      );
            }

            var getterIL = getterMethod.GetILGenerator();

            if (Options.HasFlagFast(GenerateDisposalChecks))
            {
                EmitDisposalCheck(getterIL);
            }

            GenerateSymbolPush(getterIL, propertyFieldBuilder);

            getterIL.EmitCallDirect(underlyingMethod);
            getterIL.EmitReturn();

            propertyBuilder.SetGetMethod(getterMethod);
            TargetType.DefineMethodOverride(getterMethod, actualGetMethod);
        }
示例#15
0
        private void GeneratePropertySetter
        (
            [NotNull] IntrospectivePropertyInfo property,
            [NotNull] FieldInfo propertyFieldBuilder,
            [NotNull] PropertyBuilder propertyBuilder
        )
        {
            var wrappedProperty = property.GetWrappedMember();
            var actualSetMethod = wrappedProperty.GetSetMethod();
            var setterMethod    = TargetType.DefineMethod
                                  (
                actualSetMethod.Name,
                PropertyMethodAttributes,
                actualSetMethod.CallingConvention,
                typeof(void),
                actualSetMethod.GetParameters().Select(p => p.ParameterType).ToArray()
                                  );

            MethodInfo underlyingMethod;

            if (property.PropertyType.IsPointer)
            {
                underlyingMethod = typeof(Marshal).GetMethods().First
                                   (
                    m =>
                    m.Name == nameof(Marshal.WriteIntPtr) &&
                    m.GetParameters().Length == 3
                                   );
            }
            else if (property.PropertyType.IsValueType)
            {
                underlyingMethod = typeof(Marshal).GetMethods().First
                                   (
                    m =>
                    m.Name == nameof(Marshal.StructureToPtr) &&
                    m.GetParameters().Length == 3 &&
                    m.IsGenericMethod
                                   )
                                   .MakeGenericMethod(property.PropertyType);
            }
            else
            {
                throw new NotSupportedException
                      (
                          $"The type \"{property.PropertyType.FullName}\" is not supported. Only value types or pointers are supported."
                      );
            }

            var setterIL = setterMethod.GetILGenerator();

            if (Options.HasFlagFast(GenerateDisposalChecks))
            {
                EmitDisposalCheck(setterIL);
            }

            if (property.PropertyType.IsPointer)
            {
                var explicitConvertToIntPtrFunc = typeof(IntPtr).GetMethods().First
                                                  (
                    m =>
                    m.Name == "op_Explicit"
                                                  );

                GenerateSymbolPush(setterIL, propertyFieldBuilder);
                setterIL.EmitConstantInt(0);

                setterIL.EmitLoadArgument(1);
                setterIL.EmitCallDirect(explicitConvertToIntPtrFunc);
            }
            else
            {
                setterIL.EmitLoadArgument(1);
                GenerateSymbolPush(setterIL, propertyFieldBuilder);
                setterIL.EmitConstantInt(0);
            }

            setterIL.EmitCallDirect(underlyingMethod);
            setterIL.EmitReturn();

            propertyBuilder.SetSetMethod(setterMethod);
            TargetType.DefineMethodOverride(setterMethod, actualSetMethod);
        }
示例#16
0
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var  returnType = workUnit.Definition.ReturnType;
            Type newReturnType;
            var  definition = workUnit.Definition;

            if (IsSpanType(returnType))
            {
                var genericType = returnType.GenericTypeArguments[0];

                if (!genericType.IsUnmanaged())
                {
                    throw new NotSupportedException($"Method return type must be blittable.");
                }

                newReturnType = genericType.MakePointerType();
            }
            else
            {
                newReturnType = returnType;
            }

            var parametersTypes = definition.ParameterTypes.ToArray();

            for (int i = 0; i < parametersTypes.Length; ++i)
            {
                var paramType = parametersTypes[i];
                if (IsSpanType(paramType))
                {
                    var genericParam = paramType.GenericTypeArguments[0];

                    if (genericParam.IsGenericType)
                    {
                        throw new NotSupportedException("Generic type found as Span generic argument");
                    }

                    if (!genericParam.IsUnmanaged())
                    {
                        throw new NotSupportedException("Reference or value type containing references found in Span<T> or ReadOnlySpan<T> generic parameter.");
                    }

                    parametersTypes[i] = genericParam.MakePointerType(); // genercParam.MakePointerType();
                }
            }

            MethodBuilder passthroughMethod = TargetType.DefineMethod
                                              (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                parametersTypes
                                              );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, parametersTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       parametersTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
        private void GeneratePropertySetter
        (
            [NotNull] IntrospectivePropertyInfo property,
            [NotNull] FieldInfo propertyFieldBuilder,
            [NotNull] PropertyBuilder propertyBuilder
        )
        {
            var wrappedProperty = property.GetWrappedMember();
            var actualSetMethod = wrappedProperty.GetSetMethod();
            var setterMethod    = TargetType.DefineMethod
                                  (
                actualSetMethod.Name,
                PropertyMethodAttributes,
                actualSetMethod.CallingConvention,
                typeof(void),
                actualSetMethod.GetParameters().Select(p => p.ParameterType).ToArray()
                                  );

            MethodInfo underlyingMethod;

            if (property.PropertyType.IsPointer)
            {
                underlyingMethod = typeof(Marshal).GetMethods().First
                                   (
                    m =>
                    m.Name == nameof(Marshal.WriteIntPtr) &&
                    m.GetParameters().Length == 3
                                   );
            }
            else if (property.PropertyType.IsValueType)
            {
                underlyingMethod = typeof(Marshal).GetMethods().First
                                   (
                    m =>
                    m.Name == nameof(Marshal.StructureToPtr) &&
                    m.GetParameters().Length == 3 &&
                    m.IsGenericMethod
                                   )
                                   .MakeGenericMethod(property.PropertyType);
            }
            else
            {
                throw new NotSupportedException(
                          string.Format
                          (
                              "{0} Type is not supported. Only ValueType property or Pointer Property is supported.",
                              property.PropertyType.FullName
                          )
                          );
            }

            var setterIL = setterMethod.GetILGenerator();

            if (Options.HasFlagFast(GenerateDisposalChecks))
            {
                EmitDisposalCheck(setterIL);
            }

            if (property.PropertyType.IsPointer)
            {
                var explicitConvertToIntPtrFunc = typeof(IntPtr).GetMethods().First
                                                  (
                    m =>
                    m.Name == "op_Explicit"
                                                  );

                GenerateSymbolPush(setterIL, propertyFieldBuilder);                 // Push Symbol address to stack
                setterIL.Emit(OpCodes.Ldc_I4, 0);                                   // Push 0 offset to stack

                setterIL.Emit(OpCodes.Ldarg_1);                                     // Push value to stack
                setterIL.EmitCall(OpCodes.Call, explicitConvertToIntPtrFunc, null); // Explicit Convert Pointer to IntPtr object
            }
            else
            {
                setterIL.Emit(OpCodes.Ldarg_1);
                GenerateSymbolPush(setterIL, propertyFieldBuilder);
                setterIL.Emit(OpCodes.Ldc_I4, 0); // false for deleting structure that is already stored in pointer
            }

            setterIL.EmitCall
            (
                OpCodes.Call,
                underlyingMethod,
                null
            );

            setterIL.Emit(OpCodes.Ret);

            propertyBuilder.SetSetMethod(setterMethod);
            TargetType.DefineMethodOverride(setterMethod, actualSetMethod);
        }