How to use Marshal.GetManagedThunkForUnmanagedMethodPtr and GetUnmanagedThunkForManagedMethodPtr?

431 views Asked by At

I have seen those two methods in the Marshal class often, GetManagedThunkForUnmanagedMethodPtr and GetUnmanagedThunkForManagedMethodPtr, but still I have no idea how to actually call them, or what they are good for, as the MSDN is quite unhelpful in this case. I suppose they are used in a similar manner like GetDelegateForFunctionPointer and GetFunctionPointerForDelegate, but act on a lower level.

Am I correct? I guess in the case of GetManagedThunkForUnmanagedMethodPtr, one should pass a function pointer like in GetFunctionPointerForDelegate as the first parameter, and then, judging from the coreclr source, some sort of an array and it's size (the actual CIL signature bytes, or just method tables?) Then it should return a managed function pointer.

Is this the right way to use this method, or is the method actually used for some absolutely different purpose (COM, maybe)?

Please note that I am aware this method is obsolete, infrastructure and whatever, and I am completely not going to use it production code, and probably in no code at all. I am just wondering.

1

There are 1 answers

0
IS4 On BEST ANSWER

It can be used as a basic substitute for GetDelegateForFunctionPointer in those cases where you cannot simply pass a delegate type to it. In this example, I can import vararg sprintf dynamically from any DLL I want with the correct signature:

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);
}

Now managed contains a managed function pointer, which can be called by other means (though I haven't been able to achieve it yet).

As you can see, it can be used for a limited number of purposes, most notably when you don't have the delegate type at hand. Maybe when you want to use a generic delegate for marshalling the function, but obtaining the signature and calling the managed function pointer is probably more strenuous than making a non-generic delegate.