Wie verhindere ich AccessViolationException beim Zurückgeben einer Zeichenfolge von C ++ an C # unter 64-Bit-Windows?

8

Ich verwende eine proprietäre DLL eines Drittanbieters, für die der Quellcode nicht verfügbar ist. Wrapper-Code, der mit SWIG 1.3.39 automatisch generiert wurde, steht mir jedoch zur Verfügung. Der Wrappercode besteht aus einer C ++ - Datei, die (mit einigen Headern, die die DLL beschreiben) zu einer DLL und einem C # -Projekt, das PInvoke Aufrufe an die C ++ - Wrapper-DLL macht, kompiliert.

Nach meiner Interpretation der Herstellerdokumentation habe ich alles in der Lösung je nach Zielplattform als x86 oder x64 zusammengestellt. Der Hersteller stellt sowohl die 32-Bit- als auch die 64-Bit-Version der proprietären DLL bereit, und ich habe sichergestellt, dass ich die richtige Version für den gegebenen Build verwende. Meine Maschine ist 32-Bit. Das Testen der X 86-Version meiner Anwendung auf meinem Computer in Release- oder Debug-Builds scheint einwandfrei zu funktionieren. Bei 64-Bit funktioniert die Anwendung jedoch im Debug-Modus, scheitert jedoch mit System.AccessViolationException im Freigabemodus.

Ich habe dieser nette Blogeintrag , der das Debug-vs.-Release-Problem gut zu beschreiben scheint, sowie diese Frage und Antwort , die zum Blogpost führte. Ich bin jedoch unsicher, wie das Problem in diesem Fall behoben werden kann.

Die AccessViolationException scheint das erste Mal aufzutreten, wenn eine Zeichenfolge mit einer tatsächlichen Länge vom C ++ - Wrapper zurückgegeben (oder versucht wird, zurückgegeben zu werden). Hier ist der beleidigende C # -Code:

%Vor%

Und der lästige C ++ - Code aus dem C ++ - Wrapper:

%Vor%

SWIGEXPORT wurde bereits als __declspec(dllexport) definiert. Beim Debuggen entdeckte ich SWIG_csharp_string_callback , definiert als:

%Vor%

wurde für den Delegaten (im C # -Wrapper) festgelegt:

%Vor%

Ich habe versucht, mit diesem Code zu verfahren, um Konstrukte wie Marshal.PtrToStringAut nutzlos zu verwenden. Wie kann ich dieses Problem beheben und / oder beheben?

    
Andrew 02.05.2011, 18:27
quelle

1 Antwort

3

Der richtige Weg dazu besteht darin, dass Ihr verwalteter Code den Puffer zuweist, zu dem der nicht verwaltete Code schreiben wird (die Zeichenkettendaten). Unter der Annahme, dass dies aus irgendeinem Grund nicht praktikabel ist, müssen Sie die String-Daten so zuordnen, dass sie vom verwalteten Code getrennt werden können.

Der übliche Ansatz besteht darin, den Speicher mit LocalAlloc , die dann über Marshal.FreeHGlobal . Auf diese Weise brauchen Sie nicht mehr (kludgy und offensichtlich nicht funktional) SWIG_csharp_string_callback und CreateString .

C ++ - Code :

%Vor%

C # -Code :

%Vor%

Abgesehen davon ist dieser winzige C ++ Code, den Sie gezeigt haben, ein abscheuliches C-with-class Relikt; Wenn das für den Rest der Codebasis repräsentativ ist, dann einfach, wow ...: - /

    
ildjarn 03.05.2011, 01:04
quelle