/// <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)); }
/// <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 )); }
/// <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)); } }
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); }
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); }
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); }
/// <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()); }
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 )); }
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); }
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); }
/// <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); }