Addressed more feedbacks: Moved TryGetMarshallerForDelegate from TypeLoader to S.P.I
This commit is contained in:
Родитель
bbc6b35d41
Коммит
5877f29e59
|
@ -3,13 +3,8 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Internal.TypeSystem;
|
||||
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using Interlocked = System.Threading.Interlocked;
|
||||
|
||||
namespace Internal.IL.Stubs
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -22,12 +17,14 @@ namespace Internal.IL.Stubs
|
|||
private MethodSignature _signature; // signature of the native callable marshalling stub
|
||||
private TypeDesc _delegateType;
|
||||
private MethodIL _methodIL;
|
||||
private string _name;
|
||||
|
||||
public DelegateMarshallingMethodThunk(TypeDesc owningType, TypeDesc delegateType)
|
||||
public DelegateMarshallingMethodThunk(TypeDesc owningType, TypeDesc delegateType, string name)
|
||||
{
|
||||
_owningType = owningType;
|
||||
_delegateType = delegateType;
|
||||
MethodDesc invokeMethod = delegateType.GetMethod("Invoke", null);
|
||||
_name = name;
|
||||
_delegateSignature = invokeMethod.Signature;
|
||||
_methodIL = PInvokeILEmitter.EmitIL(this, null);
|
||||
_signature = ((PInvokeILStubMethodIL)_methodIL).NativeCallableSignature;
|
||||
|
@ -41,6 +38,14 @@ namespace Internal.IL.Stubs
|
|||
}
|
||||
}
|
||||
|
||||
public override bool IsNativeCallable
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override TypeDesc OwningType
|
||||
{
|
||||
get
|
||||
|
@ -78,7 +83,7 @@ namespace Internal.IL.Stubs
|
|||
{
|
||||
get
|
||||
{
|
||||
return "ReverseDelegateStub__" + ILCompiler.DependencyAnalysis.NodeFactory.NameMangler.GetMangledTypeName(_delegateType);
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,42 +93,10 @@ namespace Internal.IL.Stubs
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
internal enum DelegateInvokeMethodParameterKind
|
||||
{
|
||||
None,
|
||||
Value,
|
||||
Reference
|
||||
}
|
||||
|
||||
|
||||
internal struct DelegateInvokeMethodSignature : IEquatable<DelegateInvokeMethodSignature>
|
||||
{
|
||||
public MethodSignature Signature;
|
||||
public bool HasReturnValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return !Signature.ReturnType.IsVoid;
|
||||
}
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return Signature.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public DelegateInvokeMethodParameterKind this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return Signature[index].IsByRef ?
|
||||
DelegateInvokeMethodParameterKind.Reference :
|
||||
DelegateInvokeMethodParameterKind.Value;
|
||||
}
|
||||
}
|
||||
public readonly MethodSignature Signature;
|
||||
|
||||
public DelegateInvokeMethodSignature(TypeDesc delegateType)
|
||||
{
|
||||
|
@ -133,28 +106,21 @@ namespace Internal.IL.Stubs
|
|||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hashCode = HasReturnValue ? 17 : 23;
|
||||
|
||||
for (int i = 0; i < Length; i++)
|
||||
{
|
||||
int value = (int)this[i] * 0x5498341 + 0x832424;
|
||||
hashCode = hashCode * 31 + value;
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
return Signature.GetHashCode();
|
||||
}
|
||||
|
||||
// TODO: Use the MarshallerKind for each parameter to compare whether two signatures are similar(ie. whether two delegates can share marshalling stubs)
|
||||
public bool Equals(DelegateInvokeMethodSignature other)
|
||||
{
|
||||
if (HasReturnValue != other.HasReturnValue)
|
||||
if (Signature.ReturnType != other.Signature.ReturnType)
|
||||
return false;
|
||||
|
||||
if (Length != other.Length)
|
||||
if (Signature.Length != other.Signature.Length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < Length; i++)
|
||||
for (int i = 0; i < Signature.Length; i++)
|
||||
{
|
||||
if (this[i] != other[i])
|
||||
if (Signature[i] != other.Signature[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1155,6 +1155,9 @@ namespace Internal.TypeSystem.Interop
|
|||
protected override void EmitMarshalReturnValueManagedToNative()
|
||||
{
|
||||
}
|
||||
protected override void EmitMarshalReturnValueNativeToManaged()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class BlittableValueMarshaller : BlittableByRefMarshaller
|
||||
|
@ -1187,9 +1190,21 @@ namespace Internal.TypeSystem.Interop
|
|||
_ilCodeStreams.CallsiteSetupCodeStream.EmitLdArg(PInvokeParameterMetadata.Index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void EmitMarshalArgumentNativeToManaged()
|
||||
{
|
||||
if (Out)
|
||||
{
|
||||
base.EmitMarshalArgumentNativeToManaged();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ilCodeStreams.CallsiteSetupCodeStream.EmitLdArg(PInvokeParameterMetadata.Index - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayMarshaller : Marshaller
|
||||
class ArrayMarshaller : Marshaller
|
||||
{
|
||||
|
||||
private Marshaller _elementMarshaller;
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace ILCompiler.DependencyAnalysis
|
|||
|
||||
foreach (var delegateEntry in factory.MetadataManager.DelegateMarshalingThunks)
|
||||
{
|
||||
Internal.TypeSystem.TypeDesc delegateType = ((Internal.IL.Stubs.DelegateMarshallingMethodThunk)delegateEntry.Value).DelegateType;
|
||||
Internal.TypeSystem.TypeDesc delegateType = delegateEntry.Value.DelegateType;
|
||||
Vertex vertex = writer.GetTuple(
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(delegateType))),
|
||||
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(delegateEntry.Value)))
|
||||
|
|
|
@ -88,16 +88,14 @@ namespace ILCompiler.DependencyAnalysis
|
|||
MethodSignature methodSig = _method.Signature;
|
||||
if (methodSig.ReturnType.IsDelegate)
|
||||
{
|
||||
var stubMethod = factory.MetadataManager.GetDelegateMarshallingStub(methodSig.ReturnType);
|
||||
dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(stubMethod), "Delegate Marshalling Stub"));
|
||||
AddPInvokeDelegateParameterDependencies(ref dependencies, factory, methodSig.ReturnType);
|
||||
}
|
||||
|
||||
for (int i=0; i < methodSig.Length; i++)
|
||||
{
|
||||
if (methodSig[i].IsDelegate)
|
||||
{
|
||||
var stubMethod = factory.MetadataManager.GetDelegateMarshallingStub(methodSig[i]);
|
||||
dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(stubMethod), "Delegate Marshalling Stub"));
|
||||
AddPInvokeDelegateParameterDependencies(ref dependencies, factory, methodSig[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +103,17 @@ namespace ILCompiler.DependencyAnalysis
|
|||
return dependencies;
|
||||
}
|
||||
|
||||
private void AddPInvokeDelegateParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter)
|
||||
{
|
||||
if (dependencies == null)
|
||||
dependencies = new DependencyList();
|
||||
|
||||
dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub");
|
||||
|
||||
var stubMethod = factory.MetadataManager.GetDelegateMarshallingStub(parameter);
|
||||
dependencies.Add(factory.MethodEntrypoint(stubMethod), "Delegate Marshalling Stub");
|
||||
}
|
||||
|
||||
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
|
||||
{
|
||||
return _methodCode;
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace ILCompiler
|
|||
new LibraryInitializerInfo("System.Private.TypeLoader"),
|
||||
new LibraryInitializerInfo("System.Private.Reflection.Execution"),
|
||||
new LibraryInitializerInfo("System.Private.DeveloperExperience.Console"),
|
||||
new LibraryInitializerInfo("System.Private.Interop"),
|
||||
};
|
||||
|
||||
private List<MethodDesc> _libraryInitializerMethods;
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace ILCompiler
|
|||
private HashSet<MethodDesc> _methodsGenerated = new HashSet<MethodDesc>();
|
||||
private HashSet<GenericDictionaryNode> _genericDictionariesGenerated = new HashSet<GenericDictionaryNode>();
|
||||
private List<TypeGVMEntriesNode> _typeGVMEntries = new List<TypeGVMEntriesNode>();
|
||||
internal Dictionary<DelegateInvokeMethodSignature, MethodDesc> DelegateMarshalingThunks = new Dictionary<DelegateInvokeMethodSignature, MethodDesc>();
|
||||
internal Dictionary<DelegateInvokeMethodSignature, DelegateMarshallingMethodThunk> DelegateMarshalingThunks = new Dictionary<DelegateInvokeMethodSignature, DelegateMarshallingMethodThunk>();
|
||||
|
||||
internal NativeLayoutInfoNode NativeLayoutInfo { get; private set; }
|
||||
|
||||
|
@ -324,13 +324,14 @@ namespace ILCompiler
|
|||
return instantiatedDynamicInvokeMethod;
|
||||
}
|
||||
|
||||
public MethodDesc GetDelegateMarshallingStub(TypeDesc del)
|
||||
internal MethodDesc GetDelegateMarshallingStub(TypeDesc delegateType)
|
||||
{
|
||||
MethodDesc thunk;
|
||||
var lookupSig = new DelegateInvokeMethodSignature(del);
|
||||
DelegateMarshallingMethodThunk thunk;
|
||||
var lookupSig = new DelegateInvokeMethodSignature(delegateType);
|
||||
if (!DelegateMarshalingThunks.TryGetValue(lookupSig, out thunk))
|
||||
{
|
||||
thunk = new DelegateMarshallingMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), del);
|
||||
string stubName = "ReverseDelegateStub__" + NodeFactory.NameMangler.GetMangledTypeName(delegateType);
|
||||
thunk = new DelegateMarshallingMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), delegateType, stubName);
|
||||
DelegateMarshalingThunks.Add(lookupSig, thunk);
|
||||
}
|
||||
return thunk;
|
||||
|
|
|
@ -61,7 +61,7 @@ LEAF_ENTRY RhpCommonStub, _TEXT
|
|||
;; rax = base address of TLS data
|
||||
;; r10 = address of context cell in thunk's data
|
||||
;; r11 = trashed
|
||||
;; r12 = trashed
|
||||
;; r8 = trashed
|
||||
|
||||
;; store thunk address in thread static
|
||||
mov r11, [r10]
|
||||
|
|
|
@ -428,6 +428,19 @@ COOP_PINVOKE_HELPER(void, CallingConventionConverter_GetStubs, (UIntNative* pRet
|
|||
{
|
||||
ASSERT_UNCONDITIONALLY("NYI");
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void *, RhpGetCommonStubAddress, ())
|
||||
{
|
||||
ASSERT_UNCONDITIONALLY("NYI");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void *, RhpGetCurrentThunkContext, ())
|
||||
{
|
||||
ASSERT_UNCONDITIONALLY("NYI");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
COOP_PINVOKE_HELPER(void, RhpETWLogLiveCom, (Int32 eventType, void * ccwHandle, void * objectId, void * typeRawValue, void * iUnknown, void * vTable, Int32 comRefCount, Int32 jupiterRefCount, Int32 flags))
|
||||
|
@ -440,16 +453,3 @@ COOP_PINVOKE_HELPER(bool, RhpETWShouldWalkCom, ())
|
|||
ASSERT_UNCONDITIONALLY("NYI");
|
||||
return false;
|
||||
}
|
||||
#ifdef USE_PORTABLE_HELPERS
|
||||
COOP_PINVOKE_HELPER(void *, RhpGetCommonStubAddress, ())
|
||||
{
|
||||
ASSERT_UNCONDITIONALLY("NYI");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void *, RhpGetCurrentThunkContext, ())
|
||||
{
|
||||
ASSERT_UNCONDITIONALLY("NYI");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// 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.CompilerServices;
|
||||
|
||||
namespace Internal.Runtime.Augments
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public abstract class InteropCallbacks
|
||||
{
|
||||
public abstract IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle);
|
||||
}
|
||||
}
|
|
@ -61,6 +61,12 @@ namespace Internal.Runtime.Augments
|
|||
s_typeLoaderCallbacks = callbacks;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static void InitializeInteropLookups(InteropCallbacks callbacks)
|
||||
{
|
||||
s_interopCallbacks = callbacks;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static void InitializeDesktopSupport(DesktopSupportCallbacks callbacks)
|
||||
{
|
||||
|
@ -770,8 +776,20 @@ namespace Internal.Runtime.Augments
|
|||
}
|
||||
}
|
||||
|
||||
internal static InteropCallbacks InteropCallbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
InteropCallbacks callbacks = s_interopCallbacks;
|
||||
if (callbacks != null)
|
||||
return callbacks;
|
||||
throw new InvalidOperationException(SR.InvalidOperation_TooEarly);
|
||||
}
|
||||
}
|
||||
|
||||
private static volatile ReflectionExecutionDomainCallbacks s_reflectionExecutionDomainCallbacks;
|
||||
private static TypeLoaderCallbacks s_typeLoaderCallbacks;
|
||||
private static InteropCallbacks s_interopCallbacks;
|
||||
|
||||
public static void ReportUnhandledException(Exception exception)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace Internal.Runtime.Augments
|
|||
public abstract IntPtr GetDelegateThunk(Delegate delegateObject, int thunkKind);
|
||||
public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle);
|
||||
public abstract bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeSignature methodSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated);
|
||||
public abstract IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle);
|
||||
|
||||
/// <summary>
|
||||
/// Register a new runtime-allocated code thunk in the diagnostic stream.
|
||||
|
|
|
@ -262,7 +262,7 @@ namespace Internal.Runtime.CompilerHelpers
|
|||
}
|
||||
else
|
||||
{
|
||||
IntPtr pTarget = RuntimeAugments.TypeLoaderCallbacks.TryGetMarshallerForDelegate(del.GetTypeHandle());
|
||||
IntPtr pTarget = RuntimeAugments.InteropCallbacks.TryGetMarshallerForDelegate(del.GetTypeHandle());
|
||||
IntPtr pContext;
|
||||
unsafe
|
||||
{
|
||||
|
|
|
@ -118,6 +118,7 @@
|
|||
<Compile Include="Internal\Runtime\Augments\RuntimeAugments.cs" />
|
||||
<Compile Include="Internal\Runtime\Augments\ReflectionExecutionDomainCallbacks.cs" />
|
||||
<Compile Include="Internal\Runtime\Augments\TypeLoaderCallbacks.cs" />
|
||||
<Compile Include="Internal\Runtime\Augments\InteropCallbacks.cs" />
|
||||
<Compile Include="Internal\Runtime\Augments\DesktopSupportCallbacks.cs" />
|
||||
<Compile Include="Internal\Runtime\Augments\DynamicDelegateAugments.cs" />
|
||||
<Compile Include="Internal\Runtime\Augments\EnumInfo.cs" />
|
||||
|
|
|
@ -1,26 +1,51 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// 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 System.Runtime;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using Internal.Runtime;
|
||||
using Internal.Runtime.Augments;
|
||||
using Internal.Runtime.CompilerServices;
|
||||
|
||||
using Internal.NativeFormat;
|
||||
using Internal.TypeSystem;
|
||||
using Internal.Runtime.TypeLoader;
|
||||
using Internal.Reflection.Execution;
|
||||
|
||||
namespace Internal.Runtime.TypeLoader
|
||||
namespace Internal.Runtime.CompilerHelpers
|
||||
{
|
||||
public sealed partial class TypeLoaderEnvironment
|
||||
internal class Callbacks : InteropCallbacks
|
||||
{
|
||||
public override IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle)
|
||||
{
|
||||
return InteropCallbackManager.Instance.TryGetMarshallerForDelegate(delegateTypeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public sealed class InteropCallbackManager
|
||||
{
|
||||
public static InteropCallbackManager Instance { get; private set; }
|
||||
|
||||
// Eager initialization called from LibraryInitializer for the assembly.
|
||||
internal static void Initialize()
|
||||
{
|
||||
Instance = new InteropCallbackManager();
|
||||
RuntimeAugments.InitializeInteropLookups(new Callbacks());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public unsafe IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle)
|
||||
{
|
||||
int delegateHashcode = delegateTypeHandle.GetHashCode();
|
|
@ -17,8 +17,12 @@ namespace Internal.Runtime.CompilerHelpers
|
|||
{
|
||||
public static void InitializeLibrary()
|
||||
{
|
||||
#if CORERT
|
||||
InteropCallbackManager.Initialize();
|
||||
#else
|
||||
__vtable_IUnknown.Initialize();
|
||||
McgModuleManager.Initialize();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
|
||||
<ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
|
||||
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
|
||||
</ItemGroup>
|
||||
<!-- TODO We should not include anything from CompilerServices directly -->
|
||||
<ItemGroup>
|
||||
|
@ -143,6 +144,12 @@
|
|||
<Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
|
||||
<Compile Include="Interop\Interop.Memory.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
|
||||
<Compile Include="Internal\Runtime\CompilerHelpers\InteropCallbackManager.cs"/>
|
||||
<Compile Include="..\..\Common\src\Internal\Runtime\MetadataBlob.cs">
|
||||
<Link>MetadataBlob.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="System\Runtime\InteropServices\ComTypes\advf.cs" />
|
||||
<Compile Include="System\Runtime\InteropServices\ComTypes\bindopts.cs" />
|
||||
|
|
|
@ -66,11 +66,6 @@ namespace Internal.Runtime.TypeLoader
|
|||
return TypeLoaderEnvironment.Instance.TryGetGenericVirtualTargetForTypeAndSlot(targetHandle, ref declaringType, genericArguments, ref methodName, ref methodSignature, out methodPointer, out dictionaryPointer, out slotUpdated);
|
||||
}
|
||||
|
||||
public override IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle)
|
||||
{
|
||||
return TypeLoaderEnvironment.Instance.TryGetMarshallerForDelegate(delegateTypeHandle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new runtime-allocated code thunk in the diagnostic stream.
|
||||
/// </summary>
|
||||
|
|
|
@ -399,7 +399,6 @@
|
|||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs" />
|
||||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.ConstructedGenericsRegistration.cs" />
|
||||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.ConstructedGenericTypesLookup.cs" />
|
||||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.DelegateMarshallerLookup.cs" />
|
||||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.cs" />
|
||||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.FieldAccess.cs" />
|
||||
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.GVMResolution.cs" />
|
||||
|
|
|
@ -59,6 +59,10 @@ namespace PInvokeTests
|
|||
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
|
||||
static extern bool ReversePInvoke_Int(Delegate_Int del);
|
||||
|
||||
delegate void Delegate_Unused();
|
||||
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
|
||||
static extern unsafe int* ReversePInvoke_Unused(Delegate_Unused del);
|
||||
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
TestBlittableType();
|
||||
|
@ -210,7 +214,17 @@ namespace PInvokeTests
|
|||
Console.WriteLine("Testing Delegate");
|
||||
Delegate_Int del = new Delegate_Int(Cube);
|
||||
ThrowIfNotEquals(true, ReversePInvoke_Int(del), "Delegate marshalling failed.");
|
||||
unsafe
|
||||
{
|
||||
//
|
||||
// We haven't instantiated Delegate_Unused and nobody
|
||||
// allocates it. If a EEType is not constructed for Delegate_Unused
|
||||
// it will fail during linking.
|
||||
//
|
||||
ReversePInvoke_Unused(null);
|
||||
}
|
||||
}
|
||||
|
||||
static int Cube(int a)
|
||||
{
|
||||
return a*a*a;
|
||||
|
|
|
@ -204,3 +204,9 @@ DLL_EXPORT void __stdcall VerifyStringBuilder(unsigned short *val)
|
|||
val[i] = (unsigned short)str[i];
|
||||
val[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
DLL_EXPORT int* __stdcall ReversePInvoke_Unused(void(__stdcall *fnPtr) (void))
|
||||
{
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче