Generate runtime interop data for structs and delegates
In order to make the Marshal APIs to work, this change generates runtime interop data for the following cases: . Delegates with UnmanagedFunctionPointerAttribute . Structs with StructLayoutAttribute . Generic parameters for Marshal generic API calls which are struct or delegate
This commit is contained in:
Родитель
f8bce0a3a9
Коммит
f63296bcb4
|
@ -21,7 +21,7 @@ namespace Internal.Runtime
|
|||
EmbeddedMetadata = 13,
|
||||
DefaultConstructorMap = 14,
|
||||
UnboxingAndInstantiatingStubMap = 15,
|
||||
InvokeInstantiations = 16, // unused
|
||||
StructMarshallingStubMap = 16,
|
||||
DelegateMarshallingStubMap = 17,
|
||||
GenericVirtualMethodTable = 18,
|
||||
InterfaceGenericVirtualMethodTable = 19,
|
||||
|
|
|
@ -93,6 +93,22 @@ namespace Internal.IL.Stubs
|
|||
}
|
||||
}
|
||||
|
||||
private TypeDesc GetNativeMethodParameterType(TypeDesc managedType, MarshalAsDescriptor marshalAs, InteropStateManager interopStateManager, bool isReturn, bool isAnsi)
|
||||
{
|
||||
TypeDesc nativeType;
|
||||
try
|
||||
{
|
||||
nativeType = MarshalHelpers.GetNativeMethodParameterType(managedType, marshalAs, interopStateManager, isReturn, isAnsi);
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// if marshalling is not supported for this type the generated stubs will emit appropriate
|
||||
// error message. We just set native type to be same as managedtype
|
||||
nativeType = managedType;
|
||||
}
|
||||
return nativeType;
|
||||
}
|
||||
|
||||
public override MethodSignature Signature
|
||||
{
|
||||
get
|
||||
|
@ -123,7 +139,7 @@ namespace Internal.IL.Stubs
|
|||
marshalAs = parameterMetadataArray[parameterIndex++].MarshalAsDescriptor;
|
||||
}
|
||||
|
||||
TypeDesc nativeReturnType = MarshalHelpers.GetNativeMethodParameterType(delegateSignature.ReturnType, null, _interopStateManager, true, isAnsi);
|
||||
TypeDesc nativeReturnType = GetNativeMethodParameterType(delegateSignature.ReturnType, null, _interopStateManager, true, isAnsi);
|
||||
for (int i = 0; i < delegateSignature.Length; i++)
|
||||
{
|
||||
int sequence = i + 1;
|
||||
|
@ -142,7 +158,7 @@ namespace Internal.IL.Stubs
|
|||
|
||||
var managedType = isByRefType ? delegateSignature[i].GetParameterType() : delegateSignature[i];
|
||||
|
||||
var nativeType = MarshalHelpers.GetNativeMethodParameterType(managedType, marshalAs, _interopStateManager, false, isAnsi);
|
||||
var nativeType = GetNativeMethodParameterType(managedType, marshalAs, _interopStateManager, false, isAnsi);
|
||||
|
||||
nativeParameterTypes[i] = isByRefType ? nativeType.MakePointerType() : nativeType;
|
||||
}
|
||||
|
|
|
@ -127,7 +127,23 @@ namespace Internal.TypeSystem.Interop
|
|||
|
||||
private NativeStructField[] _fields;
|
||||
private InteropStateManager _interopStateManager;
|
||||
private bool _hasInvalidLayout;
|
||||
|
||||
public bool HasInvalidLayout
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hasInvalidLayout;
|
||||
}
|
||||
}
|
||||
|
||||
public FieldDesc[] Fields
|
||||
{
|
||||
get
|
||||
{
|
||||
return _fields;
|
||||
}
|
||||
}
|
||||
|
||||
public NativeStructType(ModuleDesc owningModule, MetadataType managedStructType, InteropStateManager interopStateManager)
|
||||
{
|
||||
|
@ -138,6 +154,7 @@ namespace Internal.TypeSystem.Interop
|
|||
Module = owningModule;
|
||||
ManagedStructType = managedStructType;
|
||||
_interopStateManager = interopStateManager;
|
||||
_hasInvalidLayout = false;
|
||||
CalculateFields();
|
||||
}
|
||||
|
||||
|
@ -179,6 +196,7 @@ namespace Internal.TypeSystem.Interop
|
|||
// if marshalling is not supported for this type the generated stubs will emit appropriate
|
||||
// error message. We just set native type to be same as managedtype
|
||||
nativeType = managedType;
|
||||
_hasInvalidLayout = true;
|
||||
}
|
||||
|
||||
_fields[index++] = new NativeStructField(nativeType, this, field);
|
||||
|
|
|
@ -8,6 +8,7 @@ using Internal.Text;
|
|||
using Internal.TypeSystem;
|
||||
using ILCompiler.DependencyAnalysisFramework;
|
||||
using ILCompiler.DependencyAnalysis;
|
||||
using Internal.TypeSystem.Interop;
|
||||
|
||||
using DependencyList=ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;
|
||||
using DependencyListEntry=ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyListEntry;
|
||||
|
@ -87,6 +88,7 @@ namespace ILCompiler.DependencyAnalysis
|
|||
}
|
||||
|
||||
GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, method);
|
||||
AddMarshalAPIsGenericDependencies(ref dependencies, factory, method);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -118,23 +120,77 @@ namespace ILCompiler.DependencyAnalysis
|
|||
}
|
||||
}
|
||||
|
||||
private static void AddPInvokeParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter)
|
||||
public static void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
if (parameter.IsDelegate)
|
||||
if (type.IsDelegate)
|
||||
{
|
||||
dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub");
|
||||
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetForwardDelegateCreationStub(parameter)), "Delegate Marshalling Stub");
|
||||
var delegateType = type as MetadataType;
|
||||
if (delegateType != null && delegateType.HasCustomAttribute("System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"))
|
||||
{
|
||||
AddDependenciesDuePInvokeDelegate(ref dependencies, factory, delegateType);
|
||||
}
|
||||
}
|
||||
else if (Internal.TypeSystem.Interop.MarshalHelpers.IsStructMarshallingRequired(parameter))
|
||||
else if (type.IsValueType && type.IsTypeDefinition && !(type is NativeStructType))
|
||||
{
|
||||
var stub = (Internal.IL.Stubs.StructMarshallingThunk)factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(parameter);
|
||||
dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetStructMarshallingType(parameter)), "Struct Marshalling Type");
|
||||
var structType = type as MetadataType;
|
||||
if (structType != null && structType.HasCustomAttribute("System.Runtime.InteropServices", "StructLayoutAttribute"))
|
||||
{
|
||||
AddDependenciesDuePInvokeStruct(ref dependencies, factory, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// For Marshal generic APIs(eg. Marshal.StructureToPtr<T>, GetFunctionPointerForDelegate) we add
|
||||
/// the generic parameter as dependencies so that we can generate runtime data for them
|
||||
/// </summary>
|
||||
public static void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
|
||||
{
|
||||
TypeDesc owningType = method.OwningType;
|
||||
MetadataType metadataType = owningType as MetadataType;
|
||||
|
||||
if (metadataType != null)
|
||||
{
|
||||
if (metadataType.Name == "Marshal" && metadataType.Namespace == "System.Runtime.InteropServices")
|
||||
{
|
||||
foreach (TypeDesc type in method.Instantiation)
|
||||
{
|
||||
AddPInvokeParameterDependencies(ref dependencies, factory, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddPInvokeParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter)
|
||||
{
|
||||
AddDependenciesDuePInvokeDelegate(ref dependencies, factory, parameter);
|
||||
AddDependenciesDuePInvokeStruct(ref dependencies, factory, parameter);
|
||||
}
|
||||
|
||||
public static void AddDependenciesDuePInvokeDelegate(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
if (type.IsDelegate)
|
||||
{
|
||||
dependencies.Add(factory.NecessaryTypeSymbol(type), "Delegate Marshalling Stub");
|
||||
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetForwardDelegateCreationStub(type)), "Delegate Marshalling Stub");
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddDependenciesDuePInvokeStruct(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
|
||||
{
|
||||
if (MarshalHelpers.IsStructMarshallingRequired(type))
|
||||
{
|
||||
dependencies.Add(factory.NecessaryTypeSymbol(type), "Struct Marshalling Stub");
|
||||
|
||||
var stub = (Internal.IL.Stubs.StructMarshallingThunk)factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(type);
|
||||
dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetStructMarshallingType(type)), "Struct Marshalling Type");
|
||||
dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(parameter)), "Struct Marshalling stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(parameter)), "Struct Marshalling stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(type)), "Struct Marshalling stub");
|
||||
dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(type)), "Struct Marshalling stub");
|
||||
|
||||
foreach (var inlineArrayCandidate in stub.GetInlineArrayCandidates())
|
||||
{
|
||||
|
|
|
@ -2,12 +2,10 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
using Internal.Runtime;
|
||||
using Internal.Text;
|
||||
using Internal.TypeSystem;
|
||||
using Internal.IL;
|
||||
|
||||
|
@ -168,6 +166,8 @@ namespace ILCompiler.DependencyAnalysis
|
|||
// Ask the metadata manager if we have any dependencies due to reflectability.
|
||||
factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencyList, factory, _type);
|
||||
|
||||
CodeBasedDependencyAlgorithm.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);
|
||||
|
||||
return dependencyList;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,6 +203,9 @@ namespace ILCompiler.DependencyAnalysis
|
|||
{
|
||||
DependencyList dependencies = new DependencyList();
|
||||
GenericMethodsHashtableNode.GetGenericMethodsHashtableDependenciesForMethod(ref dependencies, factory, _owningMethod);
|
||||
|
||||
CodeBasedDependencyAlgorithm.AddMarshalAPIsGenericDependencies(ref dependencies, factory, _owningMethod);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
using Internal.NativeFormat;
|
||||
using Internal.Text;
|
||||
|
||||
namespace ILCompiler.DependencyAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a hash table of struct marshalling stub types generated into the image.
|
||||
/// </summary>
|
||||
internal sealed class StructMarshallingStubMapNode : ObjectNode, ISymbolDefinitionNode
|
||||
{
|
||||
private ObjectAndOffsetSymbolNode _endSymbol;
|
||||
private ExternalReferencesTableNode _externalReferences;
|
||||
|
||||
public StructMarshallingStubMapNode(ExternalReferencesTableNode externalReferences)
|
||||
{
|
||||
_endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__struct_marshalling_stub_map_End", true);
|
||||
_externalReferences = externalReferences;
|
||||
}
|
||||
|
||||
public ISymbolDefinitionNode EndSymbol => _endSymbol;
|
||||
|
||||
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
|
||||
{
|
||||
sb.Append(nameMangler.CompilationUnitPrefix).Append("__struct_marshalling_stub_map");
|
||||
}
|
||||
public int Offset => 0;
|
||||
public override bool IsShareable => false;
|
||||
|
||||
public override ObjectNodeSection Section => _externalReferences.Section;
|
||||
|
||||
public override bool StaticDependenciesAreComputed => true;
|
||||
|
||||
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
|
||||
|
||||
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
|
||||
{
|
||||
// This node does not trigger generation of other nodes.
|
||||
if (relocsOnly)
|
||||
return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
|
||||
|
||||
var writer = new NativeWriter();
|
||||
var typeMapHashTable = new VertexHashtable();
|
||||
|
||||
Section hashTableSection = writer.NewSection();
|
||||
hashTableSection.Place(typeMapHashTable);
|
||||
|
||||
foreach (var structEntry in factory.InteropStubManager.GetStructMarshallingTypes())
|
||||
{
|
||||
|
||||
// the order of data written is as follows:
|
||||
// 0. managed struct type
|
||||
// 1. native struct type
|
||||
// 2. struct marshalling thunk
|
||||
// 3. struct unmarshalling thunk
|
||||
// 4. struct cleanup thunk
|
||||
// 5. NumFields << 1 | HasInvalidLayout
|
||||
// 6 for each field
|
||||
// a. name
|
||||
// b. offset
|
||||
|
||||
var structType = structEntry.StructType;
|
||||
var nativeType = structEntry.NativeStructType;
|
||||
Vertex data= writer.GetTuple(
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.MarshallingThunk))),
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.UnmarshallingThunk))),
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.CleanupThunk)))
|
||||
);
|
||||
|
||||
uint mask = (uint)(nativeType.Fields.Length << 1) | (uint)(nativeType.HasInvalidLayout ? 1 : 0);
|
||||
data = writer.GetTuple(
|
||||
data,
|
||||
writer.GetUnsignedConstant(mask)
|
||||
);
|
||||
|
||||
for (int i = 0; i < nativeType.Fields.Length; i++)
|
||||
{
|
||||
data = writer.GetTuple(
|
||||
data,
|
||||
writer.GetStringConstant(nativeType.Fields[i].Name),
|
||||
writer.GetUnsignedConstant((uint)nativeType.Fields[i].Offset.AsInt)
|
||||
);
|
||||
}
|
||||
|
||||
Vertex vertex = writer.GetTuple(
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(structType))),
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(nativeType))),
|
||||
data
|
||||
);
|
||||
|
||||
int hashCode = structType.GetHashCode();
|
||||
typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
|
||||
}
|
||||
|
||||
byte[] hashTableBytes = writer.Save();
|
||||
|
||||
_endSymbol.SetSymbolOffset(hashTableBytes.Length);
|
||||
|
||||
return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -101,32 +101,49 @@ namespace ILCompiler
|
|||
internal struct DelegateMarshallingThunks
|
||||
{
|
||||
public TypeDesc DelegateType;
|
||||
public DelegateMarshallingMethodThunk OpenStaticDelegateMarshallingThunk;
|
||||
public DelegateMarshallingMethodThunk ClosedDelegateMarshallingThunk;
|
||||
public ForwardDelegateCreationThunk DelegateCreationThunk;
|
||||
public MethodDesc OpenStaticDelegateMarshallingThunk;
|
||||
public MethodDesc ClosedDelegateMarshallingThunk;
|
||||
public MethodDesc DelegateCreationThunk;
|
||||
}
|
||||
|
||||
internal IEnumerable<DelegateMarshallingThunks> GetDelegateMarshallingThunks()
|
||||
{
|
||||
foreach (var delegateType in _delegateMarshalingTypes)
|
||||
{
|
||||
var openStub = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType);
|
||||
var closedStub = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType);
|
||||
var delegateCreationStub = InteropStateManager.GetForwardDelegateCreationThunk(delegateType);
|
||||
yield return
|
||||
new DelegateMarshallingThunks()
|
||||
{
|
||||
DelegateType = delegateType,
|
||||
OpenStaticDelegateMarshallingThunk = openStub,
|
||||
ClosedDelegateMarshallingThunk = closedStub,
|
||||
DelegateCreationThunk = delegateCreationStub
|
||||
OpenStaticDelegateMarshallingThunk = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType),
|
||||
ClosedDelegateMarshallingThunk = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType),
|
||||
DelegateCreationThunk = InteropStateManager.GetForwardDelegateCreationThunk(delegateType)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal HashSet<NativeStructType> GetStructMarshallingTypes()
|
||||
internal struct StructMarshallingThunks
|
||||
{
|
||||
return _structMarshallingTypes;
|
||||
public TypeDesc StructType;
|
||||
public NativeStructType NativeStructType;
|
||||
public MethodDesc MarshallingThunk;
|
||||
public MethodDesc UnmarshallingThunk;
|
||||
public MethodDesc CleanupThunk;
|
||||
}
|
||||
|
||||
internal IEnumerable<StructMarshallingThunks> GetStructMarshallingTypes()
|
||||
{
|
||||
foreach (var nativeStuctType in _structMarshallingTypes)
|
||||
{
|
||||
yield return
|
||||
new StructMarshallingThunks()
|
||||
{
|
||||
StructType = nativeStuctType.ManagedStructType,
|
||||
NativeStructType = nativeStuctType,
|
||||
MarshallingThunk = InteropStateManager.GetStructMarshallingManagedToNativeThunk(nativeStuctType.ManagedStructType),
|
||||
UnmarshallingThunk = InteropStateManager.GetStructMarshallingNativeToManagedThunk(nativeStuctType.ManagedStructType),
|
||||
CleanupThunk = InteropStateManager.GetStructMarshallingCleanupThunk(nativeStuctType.ManagedStructType)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,9 @@ namespace ILCompiler
|
|||
var delegateMapNode = new DelegateMarshallingStubMapNode(commonFixupsTableNode);
|
||||
header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.DelegateMarshallingStubMap), delegateMapNode, delegateMapNode, delegateMapNode.EndSymbol);
|
||||
|
||||
var structMapNode = new StructMarshallingStubMapNode(commonFixupsTableNode);
|
||||
header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.StructMarshallingStubMap), structMapNode, structMapNode, structMapNode.EndSymbol);
|
||||
|
||||
var arrayMapNode = new ArrayMapNode(commonFixupsTableNode);
|
||||
header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ArrayMap), arrayMapNode, arrayMapNode, arrayMapNode.EndSymbol);
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
<Compile Include="Compiler\DependencyAnalysis\CallingConventionConverterKey.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\CodeBasedDependencyAlgorithm.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\DelegateMarshallingStubMapNode.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\StructMarshallingStubMapNode.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\GenericVirtualMethodTableNode.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\InterfaceGenericVirtualMethodTableNode.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\IObjectDumper.cs" />
|
||||
|
|
|
@ -12,5 +12,15 @@ namespace Internal.Runtime.Augments
|
|||
public abstract class InteropCallbacks
|
||||
{
|
||||
public abstract bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData delegateData);
|
||||
|
||||
public abstract bool TryGetStructUnsafeStructType(RuntimeTypeHandle structureTypeHandle, out RuntimeTypeHandle unsafeStructType);
|
||||
|
||||
public abstract bool TryGetStructUnmarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr unmarshalStub);
|
||||
|
||||
public abstract bool TryGetStructMarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr marshalStub);
|
||||
|
||||
public abstract bool TryGetDestroyStructureStub(RuntimeTypeHandle structureTypeHandle, out IntPtr destroyStructureStub, out bool hasInvalidLayout);
|
||||
|
||||
public abstract bool TryGetStructFieldOffset(RuntimeTypeHandle structureTypeHandle, string fieldName, out bool structExists, out uint offset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Internal.Runtime.Augments;
|
||||
using Internal.NativeFormat;
|
||||
using Internal.Runtime.TypeLoader;
|
||||
using Internal.Reflection.Execution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Internal.Runtime.CompilerHelpers
|
||||
{
|
||||
internal class Callbacks : InteropCallbacks
|
||||
{
|
||||
public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
|
||||
{
|
||||
IntPtr openStub, closedStub, delegateCreationStub;
|
||||
if (!TryGetMarshallersForDelegate(delegateTypeHandle, out openStub, out closedStub, out delegateCreationStub))
|
||||
{
|
||||
data = default(McgPInvokeDelegateData);
|
||||
return false;
|
||||
}
|
||||
|
||||
data = new global::System.Runtime.InteropServices.McgPInvokeDelegateData()
|
||||
{
|
||||
ReverseOpenStaticDelegateStub = openStub,
|
||||
ReverseStub = closedStub,
|
||||
ForwardDelegateCreationStub = delegateCreationStub
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo module, ReflectionMapBlob blob, out NativeReader reader)
|
||||
{
|
||||
byte* pBlob;
|
||||
uint cbBlob;
|
||||
|
||||
if (module.TryFindBlob((int)blob, out pBlob, out cbBlob))
|
||||
{
|
||||
reader = new NativeReader(pBlob, cbBlob);
|
||||
return true;
|
||||
}
|
||||
|
||||
reader = default(NativeReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe bool TryGetMarshallersForDelegate(RuntimeTypeHandle delegateTypeHandle, out IntPtr openStub, out IntPtr closedStub, out IntPtr delegateCreationStub)
|
||||
{
|
||||
int delegateHashcode = delegateTypeHandle.GetHashCode();
|
||||
openStub = IntPtr.Zero;
|
||||
closedStub = IntPtr.Zero;
|
||||
delegateCreationStub = IntPtr.Zero;
|
||||
|
||||
foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules())
|
||||
{
|
||||
NativeReader delegateMapReader;
|
||||
if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.DelegateMarshallingStubMap, out delegateMapReader))
|
||||
{
|
||||
NativeParser delegateMapParser = new NativeParser(delegateMapReader, 0);
|
||||
NativeHashtable delegateHashtable = new NativeHashtable(delegateMapParser);
|
||||
|
||||
ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
|
||||
externalReferences.InitializeCommonFixupsTable(module);
|
||||
|
||||
var lookup = delegateHashtable.Lookup(delegateHashcode);
|
||||
NativeParser entryParser;
|
||||
while (!(entryParser = lookup.GetNext()).IsNull)
|
||||
{
|
||||
RuntimeTypeHandle foundDelegateType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
|
||||
if (foundDelegateType.Equals(delegateTypeHandle))
|
||||
{
|
||||
byte* pOpen = (byte*)externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
byte* pClose = (byte*)externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
byte* pDelegateCreation = (byte*)externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
openStub = (IntPtr)pOpen;
|
||||
closedStub = (IntPtr)pClose;
|
||||
delegateCreationStub = (IntPtr)pDelegateCreation;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,7 @@ namespace Internal.Runtime.CompilerHelpers
|
|||
__vtable_IUnknown.Initialize();
|
||||
McgModuleManager.Initialize();
|
||||
#endif
|
||||
RuntimeAugments.InitializeInteropLookups(new Callbacks());
|
||||
RuntimeAugments.InitializeInteropLookups(RuntimeInteropData.Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Internal.Runtime.Augments;
|
||||
using Internal.NativeFormat;
|
||||
using Internal.Runtime.TypeLoader;
|
||||
using Internal.Reflection.Execution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Internal.Runtime.CompilerHelpers
|
||||
{
|
||||
internal partial class RuntimeInteropData
|
||||
{
|
||||
public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
|
||||
{
|
||||
IntPtr openStub, closedStub, delegateCreationStub;
|
||||
if (!TryGetMarshallersForDelegate(delegateTypeHandle, out openStub, out closedStub, out delegateCreationStub))
|
||||
{
|
||||
data = default(McgPInvokeDelegateData);
|
||||
return false;
|
||||
}
|
||||
|
||||
data = new global::System.Runtime.InteropServices.McgPInvokeDelegateData()
|
||||
{
|
||||
ReverseOpenStaticDelegateStub = openStub,
|
||||
ReverseStub = closedStub,
|
||||
ForwardDelegateCreationStub = delegateCreationStub
|
||||
};
|
||||
return true;
|
||||
}
|
||||
#region "Struct Data"
|
||||
public override bool TryGetStructUnsafeStructType(RuntimeTypeHandle structureTypeHandle, out RuntimeTypeHandle unsafeStructType)
|
||||
{
|
||||
IntPtr marshalStub;
|
||||
IntPtr unmarshalStub;
|
||||
IntPtr destroyStub;
|
||||
bool hasInvalidLayout;
|
||||
return TryGetMarshallersForStruct(structureTypeHandle, out unsafeStructType, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout);
|
||||
}
|
||||
|
||||
public override bool TryGetStructUnmarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr unmarshalStub)
|
||||
{
|
||||
RuntimeTypeHandle unsafeStructType;
|
||||
IntPtr marshalStub;
|
||||
IntPtr destroyStub;
|
||||
bool hasInvalidLayout;
|
||||
return TryGetMarshallersForStruct(structureTypeHandle, out unsafeStructType, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout);
|
||||
}
|
||||
|
||||
public override bool TryGetStructMarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr marshalStub)
|
||||
{
|
||||
RuntimeTypeHandle unsafeStructType;
|
||||
IntPtr unmarshalStub;
|
||||
IntPtr destroyStub;
|
||||
bool hasInvalidLayout;
|
||||
return TryGetMarshallersForStruct(structureTypeHandle, out unsafeStructType, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout);
|
||||
}
|
||||
|
||||
public override bool TryGetDestroyStructureStub(RuntimeTypeHandle structureTypeHandle, out IntPtr destroyStub, out bool hasInvalidLayout)
|
||||
{
|
||||
RuntimeTypeHandle unsafeStructType;
|
||||
IntPtr marshalStub;
|
||||
IntPtr unmarshalStub;
|
||||
return TryGetMarshallersForStruct(structureTypeHandle, out unsafeStructType, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout);
|
||||
}
|
||||
|
||||
public override bool TryGetStructFieldOffset(RuntimeTypeHandle structureTypeHandle, string fieldName, out bool structExists, out uint offset)
|
||||
{
|
||||
ExternalReferencesTable externalReferences;
|
||||
NativeParser entryParser;
|
||||
structExists = false;
|
||||
if (TryGetStructData(structureTypeHandle, out externalReferences, out entryParser))
|
||||
{
|
||||
structExists = true;
|
||||
// skip the first 4 IntPtrs
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
entryParser.GetUnsigned();
|
||||
}
|
||||
|
||||
uint mask = entryParser.GetUnsigned();
|
||||
bool hasInvalidLayout = (mask & 0x1) == 1;
|
||||
uint fieldCount = mask >> 1;
|
||||
for (uint index = 0; index < fieldCount; index++)
|
||||
{
|
||||
string name = entryParser.GetString();
|
||||
offset = entryParser.GetUnsigned();
|
||||
if (name == fieldName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
offset = 0;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo module, ReflectionMapBlob blob, out NativeReader reader)
|
||||
{
|
||||
byte* pBlob;
|
||||
uint cbBlob;
|
||||
|
||||
if (module.TryFindBlob((int)blob, out pBlob, out cbBlob))
|
||||
{
|
||||
reader = new NativeReader(pBlob, cbBlob);
|
||||
return true;
|
||||
}
|
||||
|
||||
reader = default(NativeReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe bool TryGetMarshallersForDelegate(RuntimeTypeHandle delegateTypeHandle, out IntPtr openStub, out IntPtr closedStub, out IntPtr delegateCreationStub)
|
||||
{
|
||||
int delegateHashcode = delegateTypeHandle.GetHashCode();
|
||||
openStub = IntPtr.Zero;
|
||||
closedStub = IntPtr.Zero;
|
||||
delegateCreationStub = IntPtr.Zero;
|
||||
|
||||
foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules())
|
||||
{
|
||||
NativeReader delegateMapReader;
|
||||
if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.DelegateMarshallingStubMap, out delegateMapReader))
|
||||
{
|
||||
NativeParser delegateMapParser = new NativeParser(delegateMapReader, 0);
|
||||
NativeHashtable delegateHashtable = new NativeHashtable(delegateMapParser);
|
||||
|
||||
ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
|
||||
externalReferences.InitializeCommonFixupsTable(module);
|
||||
|
||||
var lookup = delegateHashtable.Lookup(delegateHashcode);
|
||||
NativeParser entryParser;
|
||||
while (!(entryParser = lookup.GetNext()).IsNull)
|
||||
{
|
||||
RuntimeTypeHandle foundDelegateType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
|
||||
if (foundDelegateType.Equals(delegateTypeHandle))
|
||||
{
|
||||
openStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
closedStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
delegateCreationStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe bool TryGetStructData(RuntimeTypeHandle structTypeHandle, out ExternalReferencesTable externalReferences, out NativeParser entryParser)
|
||||
{
|
||||
int structHashcode = structTypeHandle.GetHashCode();
|
||||
externalReferences = default(ExternalReferencesTable);
|
||||
entryParser = default(NativeParser);
|
||||
foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules())
|
||||
{
|
||||
NativeReader structMapReader;
|
||||
if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.StructMarshallingStubMap, out structMapReader))
|
||||
{
|
||||
NativeParser structMapParser = new NativeParser(structMapReader, 0);
|
||||
NativeHashtable structHashtable = new NativeHashtable(structMapParser);
|
||||
|
||||
externalReferences.InitializeCommonFixupsTable(module);
|
||||
|
||||
var lookup = structHashtable.Lookup(structHashcode);
|
||||
while (!(entryParser = lookup.GetNext()).IsNull)
|
||||
{
|
||||
RuntimeTypeHandle foundStructType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
|
||||
if (foundStructType.Equals(structTypeHandle))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe bool TryGetMarshallersForStruct(RuntimeTypeHandle structTypeHandle, out RuntimeTypeHandle unsafeStructType, out IntPtr marshalStub, out IntPtr unmarshalStub, out IntPtr destroyStub, out bool hasInvalidLayout)
|
||||
{
|
||||
marshalStub = IntPtr.Zero;
|
||||
unmarshalStub = IntPtr.Zero;
|
||||
destroyStub = IntPtr.Zero;
|
||||
unsafeStructType = default(RuntimeTypeHandle);
|
||||
hasInvalidLayout = true;
|
||||
|
||||
ExternalReferencesTable externalReferences;
|
||||
NativeParser entryParser;
|
||||
if (TryGetStructData(structTypeHandle, out externalReferences, out entryParser))
|
||||
{
|
||||
unsafeStructType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
|
||||
marshalStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
unmarshalStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
destroyStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
|
||||
uint mask = entryParser.GetUnsigned();
|
||||
hasInvalidLayout = (mask & 0x1) == 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
|
||||
using System;
|
||||
using Internal.Runtime.Augments;
|
||||
using Internal.NativeFormat;
|
||||
using Internal.Runtime.TypeLoader;
|
||||
using Internal.Reflection.Execution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Internal.Runtime.CompilerHelpers
|
||||
{
|
||||
internal class RuntimeInteropData : InteropCallbacks
|
||||
{
|
||||
public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
|
||||
{
|
||||
return McgModuleManager.GetPInvokeDelegateData(delegateTypeHandle, out data);
|
||||
}
|
||||
|
||||
#region "Struct Data"
|
||||
public override bool TryGetStructUnsafeStructType(RuntimeTypeHandle structureTypeHandle, out RuntimeTypeHandle unsafeStructType)
|
||||
{
|
||||
return McgModuleManager.TryGetStructUnsafeStructType(structureTypeHandle, out unsafeStructType);
|
||||
}
|
||||
|
||||
public override bool TryGetStructUnmarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr unmarshalStub)
|
||||
{
|
||||
return McgModuleManager.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub);
|
||||
}
|
||||
|
||||
public override bool TryGetStructMarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr marshalStub)
|
||||
{
|
||||
return McgModuleManager.TryGetStructMarshalStub(structureTypeHandle, out marshalStub);
|
||||
}
|
||||
|
||||
public override bool TryGetDestroyStructureStub(RuntimeTypeHandle structureTypeHandle, out IntPtr destroyStructureStub, out bool hasInvalidLayout)
|
||||
{
|
||||
return McgModuleManager.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout);
|
||||
}
|
||||
|
||||
public override bool TryGetStructFieldOffset(RuntimeTypeHandle structureTypeHandle, string fieldName, out bool structExists, out uint offset)
|
||||
{
|
||||
return McgModuleManager.TryGetStructFieldOffset(structureTypeHandle, fieldName, out structExists, out offset);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -12,11 +12,19 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Internal.Runtime.CompilerHelpers
|
||||
{
|
||||
internal class Callbacks : InteropCallbacks
|
||||
internal partial class RuntimeInteropData : InteropCallbacks
|
||||
{
|
||||
public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
|
||||
private static RuntimeInteropData s_interopData;
|
||||
public static RuntimeInteropData Instance
|
||||
{
|
||||
return McgModuleManager.GetPInvokeDelegateData(delegateTypeHandle, out data);
|
||||
get
|
||||
{
|
||||
if (s_interopData == null)
|
||||
{
|
||||
s_interopData = new RuntimeInteropData();
|
||||
}
|
||||
return s_interopData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -139,8 +139,9 @@
|
|||
<Compile Include="System\Runtime\InteropServices\WindowsRuntime\EventRegistrationToken.cs" />
|
||||
<Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
|
||||
<Compile Include="Interop\Interop.Memory.cs" />
|
||||
<Compile Condition="'$(IsProjectNLibrary)' == 'true'" Include="Internal\Runtime\CompilerHelpers\Callbacks.ProjectN.cs"/>
|
||||
<Compile Condition="'$(IsProjectNLibrary)' != 'true'" Include="Internal\Runtime\CompilerHelpers\Callbacks.CoreRT.cs"/>
|
||||
<Compile Include="Internal\Runtime\CompilerHelpers\RuntimeInteropData.cs"/>
|
||||
<Compile Condition="'$(IsProjectNLibrary)' == 'true'" Include="Internal\Runtime\CompilerHelpers\RuntimeInteropData.ProjectN.cs"/>
|
||||
<Compile Condition="'$(IsProjectNLibrary)' != 'true'" Include="Internal\Runtime\CompilerHelpers\RuntimeInteropData.CoreRT.cs"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
|
||||
<Compile Include="..\..\Common\src\Internal\Runtime\MetadataBlob.cs">
|
||||
|
|
|
@ -20,6 +20,7 @@ using System.Security;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using Internal.Runtime.CompilerHelpers;
|
||||
|
||||
namespace System.Runtime.InteropServices
|
||||
{
|
||||
|
@ -178,7 +179,7 @@ namespace System.Runtime.InteropServices
|
|||
RuntimeTypeHandle typeHandle = t.TypeHandle;
|
||||
|
||||
RuntimeTypeHandle unsafeStructType;
|
||||
if (McgModuleManager.TryGetStructUnsafeStructType(typeHandle, out unsafeStructType))
|
||||
if (RuntimeInteropData.Instance.TryGetStructUnsafeStructType(typeHandle, out unsafeStructType))
|
||||
{
|
||||
return unsafeStructType.GetValueTypeSize();
|
||||
}
|
||||
|
@ -216,7 +217,7 @@ namespace System.Runtime.InteropServices
|
|||
{
|
||||
bool structExists;
|
||||
uint offset;
|
||||
if (McgModuleManager.TryGetStructFieldOffset(t.TypeHandle, fieldName, out structExists, out offset))
|
||||
if (RuntimeInteropData.Instance.TryGetStructFieldOffset(t.TypeHandle, fieldName, out structExists, out offset))
|
||||
{
|
||||
return new IntPtr(offset);
|
||||
}
|
||||
|
@ -1096,7 +1097,7 @@ namespace System.Runtime.InteropServices
|
|||
}
|
||||
|
||||
IntPtr unmarshalStub;
|
||||
if (McgModuleManager.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
|
||||
if (RuntimeInteropData.Instance.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
|
||||
{
|
||||
InteropExtensions.PinObjectAndCall(structure,
|
||||
unboxedStructPtr =>
|
||||
|
@ -1191,7 +1192,7 @@ namespace System.Runtime.InteropServices
|
|||
|
||||
bool isBlittable = false; // whether Mcg treat this struct as blittable struct
|
||||
IntPtr marshalStub;
|
||||
if (McgModuleManager.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
|
||||
if (RuntimeInteropData.Instance.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
|
||||
{
|
||||
if (marshalStub != IntPtr.Zero)
|
||||
{
|
||||
|
@ -1279,7 +1280,7 @@ namespace System.Runtime.InteropServices
|
|||
|
||||
IntPtr destroyStructureStub;
|
||||
bool hasInvalidLayout;
|
||||
if (McgModuleManager.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout))
|
||||
if (RuntimeInteropData.Instance.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout))
|
||||
{
|
||||
if (hasInvalidLayout)
|
||||
throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.GetDisplayName());
|
||||
|
|
|
@ -519,6 +519,16 @@ namespace PInvokeTests
|
|||
|
||||
public ExplicitStruct f2;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct TestStruct2
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public int f1;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public bool f2;
|
||||
}
|
||||
|
||||
private static void TestStruct()
|
||||
{
|
||||
|
@ -582,6 +592,24 @@ namespace PInvokeTests
|
|||
ius.inlineString = "Hello World";
|
||||
|
||||
#if !CODEGEN_CPP
|
||||
|
||||
TestStruct2 ts = new Program.TestStruct2() { f1 = 100, f2 = true };
|
||||
int size = Marshal.SizeOf<TestStruct2>(ts);
|
||||
IntPtr memory = Marshal.AllocHGlobal(size);
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr<Program.TestStruct2>(ts, memory, false);
|
||||
TestStruct2 ts2 = Marshal.PtrToStructure<Program.TestStruct2>(memory);
|
||||
ThrowIfNotEquals(true, ts2.f1 == 100 && ts2.f2 == true, "Struct marshalling Marshal API failed");
|
||||
|
||||
IntPtr offset = Marshal.OffsetOf<Program.TestStruct2>("f2");
|
||||
ThrowIfNotEquals(new IntPtr(8), offset, "Struct marshalling OffsetOf failed.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(memory);
|
||||
}
|
||||
|
||||
ThrowIfNotEquals(true, InlineArrayTest(ref ias, ref ius), "inline array marshalling failed");
|
||||
bool pass = true;
|
||||
for (short i = 0; i < 128; i++)
|
||||
|
|
Загрузка…
Ссылка в новой задаче