C# 如何使用Marshal.GetManagedThunkForUnmanagedMethodPtr和GetUnmanagedThunkForManagedMethodPtr?

C# 如何使用Marshal.GetManagedThunkForUnmanagedMethodPtr和GetUnmanagedThunkForManagedMethodPtr?,c#,.net,interop,marshalling,unmanaged,C#,.net,Interop,Marshalling,Unmanaged,我经常在类中看到这两个方法,但是我仍然不知道如何实际调用它们,或者它们有什么好处,因为在这种情况下MSDN是毫无帮助的。我想它们的使用方式与GetDelegateForFunctionPointer和GetFunctionPointerForDelegate类似,但作用级别较低 我说得对吗?我猜在GetManagedThunkForUnmanagedMethodPtr的情况下,应该传递一个函数指针,如GetFunctionPointerForDelegate中的函数指针作为第一个参数,然后,从c

我经常在类中看到这两个方法,但是我仍然不知道如何实际调用它们,或者它们有什么好处,因为在这种情况下MSDN是毫无帮助的。我想它们的使用方式与GetDelegateForFunctionPointer和GetFunctionPointerForDelegate类似,但作用级别较低

我说得对吗?我猜在GetManagedThunkForUnmanagedMethodPtr的情况下,应该传递一个函数指针,如GetFunctionPointerForDelegate中的函数指针作为第一个参数,然后,从coreclr源判断,某种数组及其大小(实际的CIL签名字节,或者仅仅是方法表?),然后它应该返回一个托管函数指针

这是使用此方法的正确方法,还是该方法实际用于某些完全不同的目的(可能是COM)


请注意,我知道这个方法已经过时了,不管是基础设施还是其他什么,我完全不打算使用它的生产代码,可能根本就没有代码。我只是想知道。

在不能简单地向其传递委托类型的情况下,它可以作为GetDelegateForFunctionPointer的基本替代品。在本例中,我可以使用正确的签名从我想要的任何DLL动态导入vararg
sprintf

private class Interop
{
    //This method exists just to provide its signature, it cannot be called directly
    [DllImport("\0", CallingConvention = CallingConvention.Cdecl)]
    public static extern int sprintf(StringBuilder buffer, string format, __arglist);

    //Loads a DLL library
    [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
    public static extern IntPtr LoadLibrary(string lpFileName);

    //Obtains a pointer to a function from a library
    [DllImport("kernel32", SetLastError=true, CharSet=CharSet.Ansi)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
}

var mi = typeof(Interop).GetMethod("sprintf");
byte[] sig = typeof(Interop).Module.ResolveSignature(mi.MetadataToken);
//the signature of the method is 05-02-08-12-80-8D-0E (varags, 2 parameters, returning int, class parameter, string parameter)

var lib = Interop.LoadLibrary("msvcrt.dll");
var proc = Interop.GetProcAddress(lib, "sprintf");
IntPtr managed;
fixed(byte* sigb = sig)
{
    //the signature is passed to the method
    managed = Marshal.GetManagedThunkForUnmanagedMethodPtr(proc, (IntPtr)sigb, sig.Length);
}
现在
managed
包含一个托管函数指针,可以通过其他方式调用它(尽管我还没有实现它)


如您所见,它可以用于有限的目的,尤其是当您手头没有委托类型时。可能是当您想使用泛型委托来封送函数时,但是获取签名和调用托管函数指针可能比使用非泛型委托更加困难。

Microsoft在.NET 1.0中犯了很多错误。训练轮,每个人都必须从某个地方开始。在.NET 2.0中,它被更高级的Marshal.GetFunctionPointerForDelegate()取代。委托声明提供了无希望的pbSignature参数的等价物。永远不要相信在框架方法中添加匈牙利符号的程序员:)@HansPassant好建议!似乎签名实际上是CIL MethodDescSig,因为尝试传递“00 00 01”数组会为
操作
类型的方法提供完全可调用的thunk。我已经有了在运行时提取方法签名的方法,所以我现在可以调用这些方法了。尽管我仍然想知道,在过去,编译器制造商应该如何调用这些方法。@HansPassant,我想这不到一个小时。而且,花得好的空闲时间不会浪费。☺