2016-12-22 2 views
0

Ich habe diese beiden Methoden in der oft für GetManagedThunkForUnmanagedMethodPtr und GetUnmanagedThunkForManagedMethodPtr, aber noch habe ich keine Ahnung, wie man sie eigentlich nennen, oder was sie sind gut Marshal Klasse gesehen, wie die MSDN recht wenig hilfreich ist in dieser Fall. Ich nehme an, sie werden in ähnlicher Weise wie GetDelegateForFunctionPointer und GetFunctionPointerForDelegate verwendet, aber handeln auf einer niedrigeren Ebene.Wie Marshal.GetManagedThunkForUnmanagedMethodPtr und GetUnmanagedThunkForManagedMethodPtr verwenden?

Bin ich richtig? Ich denke, im Fall von GetManagedThunkForUnmanagedMethodPtr, sollte man einen Funktionszeiger wie in GetFunctionPointerForDelegate als erster Parameter übergeben, und dann, von der CoreCrr-Quelle zu urteilen, eine Art von Array und seine Größe (die tatsächlichen CIL-Signatur Bytes, oder nur Methodentabellen?) Dann sollte es einen verwalteten Funktionszeiger zurückgeben.

Ist dies der richtige Weg, diese Methode zu verwenden, oder wird die Methode tatsächlich für einen ganz anderen Zweck verwendet (COM, vielleicht)?

Bitte beachten Sie, dass ich weiß, dass diese Methode veraltet ist, Infrastruktur und was auch immer, und ich werde es komplett Produktionscode verwenden, und wahrscheinlich überhaupt keinen Code. Ich wundere mich.

+1

Microsoft hat eine Menge Fehler in .NET 1.0 gemacht. Trainingsräder, jeder muss irgendwo anfangen. Es wurde in .NET 2.0 von dem viel besseren Marshal.GetFunctionPointerForDelegate() ersetzt. Die Delegatendeklaration liefert das Äquivalent des hoffnungslosen * pbSignature * -Arguments. Traue niemals einem Programmierer, der eine Framework-Methode ungarische Notation hinzufügt :) –

+0

@HansPassant Guter Rat! Es scheint, dass die Signatur tatsächlich die CIL MethodDescSig ist, da der Versuch, ein Array von "00 00 01" zu übergeben, Ihnen ein perfekt aufrufbares Thunk für eine "Action" -Methode liefert. Und ich habe bereits eine Möglichkeit, die Signatur einer Methode zur Laufzeit zu extrahieren, damit ich diese Methoden jetzt aufrufen kann. Allerdings frage ich mich immer noch, wie die Compiler-Hersteller diese Methoden in früheren Zeiten nennen sollten. – IllidanS4

+0

@HansPassant Ich denke, es war kürzer als eine Stunde. Und die gut verbrachte Zeit ist nicht verloren. ☺ – IllidanS4

Antwort

0

Es kann als grundlegender Ersatz für GetDelegateForFunctionPointer in den Fällen verwendet werden, in denen Sie nicht einfach einen Delegattyp an es übergeben können. In diesem Beispiel kann ich Vararg sprintf dynamisch von jedem DLL importiere ich mit der richtigen Signatur will:

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

Jetzt managed einen verwalteten Funktionszeiger enthält, die mit anderen Mitteln aufgerufen werden können (obwohl ich nicht in der Lage gewesen, um es noch zu erreichen).

Wie Sie sehen können, kann es für eine begrenzte Anzahl von Zwecken verwendet werden, vor allem, wenn Sie nicht den Delegate-Typ zur Hand haben. Vielleicht, wenn Sie einen generischen Delegaten zum Marshalling der Funktion verwenden möchten, aber das Abrufen der Signatur und das Aufrufen des verwalteten Funktionszeigers ist wahrscheinlich anstrengender als das Erstellen eines nicht generischen Delegaten.

Verwandte Themen