public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); MarshalDirection direction = MarshalDirection.Forward; MethodSignature methodSig = targetMethod.Signature; PInvokeFlags flags = targetMethod.GetPInvokeMethodMetadata().Flags; ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata(); Marshaller[] marshallers = new Marshaller[methodSig.Length + 1]; ParameterMetadata parameterMetadata; for (int i = 0, parameterIndex = 0; i < marshallers.Length; i++) { Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index); if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index) { // if we don't have metadata for the parameter, create a dummy one parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null); } else { Debug.Assert(i == parameterMetadataArray[parameterIndex].Index); parameterMetadata = parameterMetadataArray[parameterIndex++]; } TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1]; //first item is the return type marshallers[i] = CreateMarshaller(parameterType, parameterIndex, methodSig.GetEmbeddedSignatureData(), MarshallerType.Argument, parameterMetadata.MarshalAsDescriptor, direction, marshallers, parameterMetadata.Index, flags, parameterMetadata.In, parameterMetadata.Out, parameterMetadata.Return); } return(marshallers); }
private Marshaller[] InitializeMarshallers() { Debug.Assert(_interopStateManager != null); MarshalAsDescriptor[] marshalAsDescriptors = ((MetadataType)ManagedType).GetFieldMarshalAsDescriptors(); Marshaller[] marshallers = new Marshaller[marshalAsDescriptors.Length]; PInvokeFlags flags = new PInvokeFlags(); if (ManagedType.PInvokeStringFormat == PInvokeStringFormat.UnicodeClass || ManagedType.PInvokeStringFormat == PInvokeStringFormat.AutoClass) { flags.CharSet = CharSet.Unicode; } else { flags.CharSet = CharSet.Ansi; } int index = 0; foreach (FieldDesc field in ManagedType.GetFields()) { if (field.IsStatic) { continue; } marshallers[index] = Marshaller.CreateMarshaller(field.FieldType, MarshallerType.Field, marshalAsDescriptors[index], (ThunkType == StructMarshallingThunkType.NativeToManaged) ? MarshalDirection.Reverse : MarshalDirection.Forward, marshallers, _interopStateManager, index, flags, isIn: true, /* Struct fields are considered as IN within the helper*/ isOut: false, isReturn: false); index++; } return(marshallers); }
public static bool IsMarshallingRequired(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); if (targetMethod.IsUnmanagedCallersOnly) { return(true); } PInvokeMetadata metadata = targetMethod.GetPInvokeMethodMetadata(); PInvokeFlags flags = metadata.Flags; if (flags.SetLastError) { return(true); } if (!flags.PreserveSig) { return(true); } if (MarshalHelpers.ShouldCheckForPendingException(targetMethod.Context.Target, metadata)) { return(true); } var marshallers = GetMarshallersForMethod(targetMethod); for (int i = 0; i < marshallers.Length; i++) { if (marshallers[i].IsMarshallingRequired()) { return(true); } } return(false); }
private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, InteropStateManager interopStateManager) { Debug.Assert(targetMethod.IsPInvoke || targetMethod is DelegateMarshallingMethodThunk || targetMethod is CalliMarshallingMethodThunk); _targetMethod = targetMethod; _pInvokeILEmitterConfiguration = pinvokeILEmitterConfiguration; _pInvokeMetadata = targetMethod.GetPInvokeMethodMetadata(); _interopStateManager = interopStateManager; // // targetMethod could be either a PInvoke or a DelegateMarshallingMethodThunk // ForwardNativeFunctionWrapper method thunks are marked as PInvokes, so it is // important to check them first here so that we get the right flags. // if (_targetMethod is DelegateMarshallingMethodThunk delegateMethod) { _flags = ((EcmaType)delegateMethod.DelegateType.GetTypeDefinition()).GetDelegatePInvokeFlags(); } else { _flags = _pInvokeMetadata.Flags; } _marshallers = InitializeMarshallers(targetMethod, interopStateManager, _flags); }
public static PInvokeFlags GetDelegatePInvokeFlags(this EcmaType type) { PInvokeFlags flags = new PInvokeFlags(PInvokeAttributes.PreserveSig); if (!type.IsDelegate) { return(flags); } var customAttributeValue = type.GetDecodedCustomAttribute( "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); if (customAttributeValue == null) { return(flags); } if (!customAttributeValue.HasValue) { return(flags); } if (customAttributeValue.Value.FixedArguments.Length == 1) { CallingConvention callingConvention = (CallingConvention)customAttributeValue.Value.FixedArguments[0].Value; switch (callingConvention) { case CallingConvention.StdCall: flags.UnmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConventionStdCall; break; case CallingConvention.Cdecl: flags.UnmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConventionCdecl; break; case CallingConvention.ThisCall: flags.UnmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConventionThisCall; break; case CallingConvention.Winapi: // Platform default break; } } foreach (var namedArgument in customAttributeValue.Value.NamedArguments) { if (namedArgument.Name == "CharSet") { flags.CharSet = (CharSet)namedArgument.Value; } else if (namedArgument.Name == "BestFitMapping") { flags.BestFitMapping = (bool)namedArgument.Value; } else if (namedArgument.Name == "SetLastError") { flags.SetLastError = (bool)namedArgument.Value; } else if (namedArgument.Name == "ThrowOnUnmappableChar") { flags.ThrowOnUnmappableChar = (bool)namedArgument.Value; } } return(flags); }
private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, InteropStateManager interopStateManager, PInvokeFlags flags) { bool isDelegate = targetMethod is DelegateMarshallingMethodThunk; MethodSignature methodSig = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).DelegateSignature : targetMethod.Signature; MarshalDirection direction = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).Direction: MarshalDirection.Forward; int indexOffset = 0; if (!methodSig.IsStatic && direction == MarshalDirection.Forward) { // For instance methods(eg. Forward delegate marshalling thunk), first argument is // the instance indexOffset = 1; } ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata(); Marshaller[] marshallers = new Marshaller[methodSig.Length + 1]; int parameterIndex = 0; ParameterMetadata parameterMetadata; for (int i = 0; i < marshallers.Length; i++) { Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index); if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index) { // if we don't have metadata for the parameter, create a dummy one parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null); } else { Debug.Assert(i == parameterMetadataArray[parameterIndex].Index); parameterMetadata = parameterMetadataArray[parameterIndex++]; } TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1]; //first item is the return type marshallers[i] = Marshaller.CreateMarshaller(parameterType, MarshallerType.Argument, parameterMetadata.MarshalAsDescriptor, direction, marshallers, interopStateManager, indexOffset + parameterMetadata.Index, flags, parameterMetadata.In, parameterMetadata.Out, parameterMetadata.Return ); } return(marshallers); }
private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, InteropStateManager interopStateManager, PInvokeFlags flags) { MarshalDirection direction = MarshalDirection.Forward; MethodSignature methodSig; switch (targetMethod) { case DelegateMarshallingMethodThunk delegateMethod: methodSig = delegateMethod.DelegateSignature; direction = delegateMethod.Direction; break; case CalliMarshallingMethodThunk calliMethod: methodSig = calliMethod.TargetSignature; break; default: methodSig = targetMethod.Signature; break; } int indexOffset = 0; if (!methodSig.IsStatic && direction == MarshalDirection.Forward) { // For instance methods(eg. Forward delegate marshalling thunk), first argument is // the instance indexOffset = 1; } ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata(); Marshaller[] marshallers = new Marshaller[methodSig.Length + 1]; int parameterIndex = 0; ParameterMetadata parameterMetadata; for (int i = 0; i < marshallers.Length; i++) { Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index); if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index) { // if we don't have metadata for the parameter, create a dummy one parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null); } else { Debug.Assert(i == parameterMetadataArray[parameterIndex].Index); parameterMetadata = parameterMetadataArray[parameterIndex++]; } TypeDesc parameterType; bool isHRSwappedRetVal = false; if (i == 0) { // First item is the return type parameterType = methodSig.ReturnType; if (!flags.PreserveSig && !parameterType.IsVoid) { // PreserveSig = false can only show up an regular forward PInvokes Debug.Assert(direction == MarshalDirection.Forward); parameterType = methodSig.Context.GetByRefType(parameterType); isHRSwappedRetVal = true; } } else { parameterType = methodSig[i - 1]; } marshallers[i] = Marshaller.CreateMarshaller(parameterType, parameterIndex, methodSig.GetEmbeddedSignatureData(), MarshallerType.Argument, parameterMetadata.MarshalAsDescriptor, direction, marshallers, interopStateManager, indexOffset + parameterMetadata.Index, flags, parameterMetadata.In, isHRSwappedRetVal ? true : parameterMetadata.Out, isHRSwappedRetVal ? false : parameterMetadata.Return ); } return(marshallers); }
public PInvokeMethodFixupNode PInvokeMethodFixup(string moduleName, string entryPointName, PInvokeFlags flags) { return(_pInvokeMethodFixups.GetOrAdd(Tuple.Create(moduleName, entryPointName, flags))); }
public PInvokeMethodFixupNode(string moduleName, string entryPointName, PInvokeFlags flags) { _moduleName = moduleName; _entryPointName = entryPointName; _flags = flags; }
public PInvokeMethodFixupNode(PInvokeModuleData moduleData, string entryPointName, PInvokeFlags flags) { _moduleData = moduleData; _entryPointName = entryPointName; _flags = flags; }
public override MethodIL EmitIL() { try { Debug.Assert(_interopStateManager != null); Marshaller[] marshallers = new Marshaller[GetNumberOfInstanceFields()]; MarshalAsDescriptor[] marshalAsDescriptors = ((MetadataType)ManagedType).GetFieldMarshalAsDescriptors(); PInvokeFlags flags = new PInvokeFlags(); if (ManagedType.PInvokeStringFormat == PInvokeStringFormat.UnicodeClass || ManagedType.PInvokeStringFormat == PInvokeStringFormat.AutoClass) { flags.CharSet = CharSet.Unicode; } else { flags.CharSet = CharSet.Ansi; } int index = 0; foreach (FieldDesc field in ManagedType.GetFields()) { if (field.IsStatic) { continue; } marshallers[index] = Marshaller.CreateMarshaller(field.FieldType, MarshallerType.Field, marshalAsDescriptors[index], (ThunkType == StructMarshallingThunkType.NativeToManage) ? MarshalDirection.Reverse : MarshalDirection.Forward, marshallers, _interopStateManager, index, flags, isIn: true, /* Struct fields are considered as IN within the helper*/ isOut: false, isReturn: false); index++; } PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); if (ThunkType == StructMarshallingThunkType.Cleanup) { return(EmitCleanupIL(pInvokeILCodeStreams, marshallers)); } else { return(EmitMarshallingIL(pInvokeILCodeStreams, marshallers)); } } catch (NotSupportedException) { string message = "Struct '" + ((MetadataType)ManagedType).Name + "' requires non-trivial marshalling that is not yet supported by this compiler."; return(MarshalHelpers.EmitExceptionBody(message, this)); } catch (InvalidProgramException ex) { Debug.Assert(!String.IsNullOrEmpty(ex.Message)); return(MarshalHelpers.EmitExceptionBody(ex.Message, this)); } }