Ich habe die folgende C++ Funktionsdefinition, die ich durch PInvoke von verwalteten Code aufzurufen bin versucht:Richtiger Weg, um SIZE_T * zu marshalieren?
bool FooBar(SIZE_T* arg1);
Meine verwaltete Erklärung sah wie folgt aus:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref uint arg1);
Einige von euch das gleiche feststellen kann Bug habe ich schließlich getan. Dies ist nicht 64-Bit-Portable. SIZE_T hat eine variable Größe (32-64 Bit) wie der Zeiger darauf. Bei der verwalteten Größe wird der Zeiger korrekt in 64-Bit übersetzt, aber die Uint nicht, und Sie können mit Müll in den oberen Bits von arg1 enden. Dies war ein besonders hartnäckiger Fehler, da der Müll oft nur Nullen :(
Die einzige Lösung, die ich an der Arbeit bekommen habe, ist die folgende verwaltete Deklaration:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref IntPtr arg1);
Dies funktioniert natürlich, weil IntPtr seine Größe variieren kann In meinem Code behandle ich IntPtr einfach als Ganzzahl, und es funktioniert, obwohl es wie ein hässlicher Hack aussieht. Es scheint mir, dass es eine Möglichkeit geben sollte, dies richtig zu spezifizieren, vielleicht mit UnmanagedType.SysUInt, aber ich war es nicht in der Lage, mit einer anderen Arbeitslösung zu arbeiten
Ich sehe es als ein hässlicher Hack, weil IntPtr einen Zeiger auf etwas darstellen sollte. Ich behandle es einfach direkt als Integer. SysUInt gibt ausdrücklich an, dass es sich um eine Darstellung variabler Größe einer Uint handelt. Genau das, was ich will, außer dass ich nicht herausfinden kann, wie man es als SysUInt-Pointer, anstatt als SysUInt, richtig einrichtet. – sooniln
Sie verwenden einen Zeiger auf SIZE_T als Argument, Soonil. IntPtr sieht sehr passend aus –
Sie werden bemerken, dass ich IntPtr nicht verwende, aber ich verwende ref IntPtr. – sooniln