如何使用Marshal.GetManagedThunkForUnmanagedMethodPtr和GetUnmanagedThunkForManagedMethodPtr?
How to use Marshal.GetManagedThunkForUnmanagedMethodPtr and GetUnmanagedThunkForManagedMethodPtr?
我在Marshal class often, GetManagedThunkForUnmanagedMethodPtr and GetUnmanagedThunkForManagedMethodPtr中看到了这两个方法,但我仍然不知道如何实际调用它们,或者它们有什么用,因为MSDN 在这种情况下毫无帮助。我想它们的使用方式与 GetDelegateForFunctionPointer 和 GetFunctionPointerForDelegate 类似,但在较低级别上起作用。
我说的对吗?我想在 GetManagedThunkForUnmanagedMethodPtr 的情况下,应该像 GetFunctionPointerForDelegate 那样传递一个函数指针作为第一个参数,然后从 coreclr 源代码判断,某种数组及其大小(实际的 CIL 签名字节,或者只是方法表?)然后它应该 return 一个托管函数指针。
这是使用此方法的正确方法,还是该方法实际用于某些完全不同的目的(可能是 COM)?
请注意,我知道这种方法、基础设施和其他任何东西都已过时,我完全不会在生产代码中使用它,并且可能根本不会使用它。我只是想知道。
在无法简单地将委托类型传递给它的情况下,它可以用作 GetDelegateForFunctionPointer 的基本替代品。在此示例中,我可以使用正确的签名从任何我想要的 DLL 中动态导入 vararg sprintf
:
private class Interop
{
//This method exists just to provide its signature, it cannot be called directly
[DllImport("[=10=]", 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
包含一个托管函数指针,可以通过其他方式调用(虽然我还没有实现)。
如您所见,它的用途有限,尤其是当您手头没有委托类型时。也许当您想使用通用委托来编组函数时,但获取签名和调用托管函数指针可能比创建非通用委托更费力。
我在Marshal class often, GetManagedThunkForUnmanagedMethodPtr and GetUnmanagedThunkForManagedMethodPtr中看到了这两个方法,但我仍然不知道如何实际调用它们,或者它们有什么用,因为MSDN 在这种情况下毫无帮助。我想它们的使用方式与 GetDelegateForFunctionPointer 和 GetFunctionPointerForDelegate 类似,但在较低级别上起作用。
我说的对吗?我想在 GetManagedThunkForUnmanagedMethodPtr 的情况下,应该像 GetFunctionPointerForDelegate 那样传递一个函数指针作为第一个参数,然后从 coreclr 源代码判断,某种数组及其大小(实际的 CIL 签名字节,或者只是方法表?)然后它应该 return 一个托管函数指针。
这是使用此方法的正确方法,还是该方法实际用于某些完全不同的目的(可能是 COM)?
请注意,我知道这种方法、基础设施和其他任何东西都已过时,我完全不会在生产代码中使用它,并且可能根本不会使用它。我只是想知道。
在无法简单地将委托类型传递给它的情况下,它可以用作 GetDelegateForFunctionPointer 的基本替代品。在此示例中,我可以使用正确的签名从任何我想要的 DLL 中动态导入 vararg sprintf
:
private class Interop
{
//This method exists just to provide its signature, it cannot be called directly
[DllImport("[=10=]", 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
包含一个托管函数指针,可以通过其他方式调用(虽然我还没有实现)。
如您所见,它的用途有限,尤其是当您手头没有委托类型时。也许当您想使用通用委托来编组函数时,但获取签名和调用托管函数指针可能比创建非通用委托更费力。