Gewusst wie: Marshallen von ANSI-Zeichenfolgen mit C++-Interop
In diesem Thema wird veranschaulicht, wie ANSI-Zeichenfolgen mithilfe von C++-Interop übergeben werden können, das .NET Framework String stellt jedoch Zeichenfolgen im Unicode-Format dar. Daher ist die Konvertierung in ANSI ein zusätzlicher Schritt. Die Zusammenarbeit mit anderen Zeichenfolgentypen finden Sie in den folgenden Themen:
Vorgehensweise: Marshallen von Unicode-Zeichenfolgen mit C++-Interop
Vorgehensweise: Marshallen von COM-Zeichenfolgen mit C++-Interop
In den folgenden Codebeispielen werden die verwalteten, nicht verwalteten #pragma Direktiven verwendet, um verwaltete und nicht verwaltete Funktionen in derselben Datei zu implementieren, diese Funktionen funktionieren jedoch in gleicher Weise, wenn sie in separaten Dateien definiert sind. Da Dateien, die nur nicht verwaltete Funktionen enthalten, nicht mit /clr (Common Language Runtime Compilation) kompiliert werden müssen, können sie ihre Leistungsmerkmale beibehalten.
Beispiel: Übergeben einer ANSI-Zeichenfolge
Das Beispiel veranschaulicht das Übergeben einer ANSI-Zeichenfolge von einer verwalteten an eine nicht verwaltete Funktion mithilfe von StringToHGlobalAnsi. Diese Methode weist Speicher für den nicht verwalteten Heap zu und gibt die Adresse nach dem Ausführen der Konvertierung zurück. Dies bedeutet, dass kein Anheften erforderlich ist (da speicher auf dem GC-Heap nicht an die nicht verwaltete Funktion übergeben wird) und dass der von StringToHGlobalAnsi der IntPtr zurückgegebene Code explizit freigegeben werden muss oder ein Speicherverlust resultiert.
// MarshalANSI1.cpp
// compile with: /clr
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma unmanaged
void NativeTakesAString(const char* p) {
printf_s("(native) received '%s'\n", p);
}
#pragma managed
int main() {
String^ s = gcnew String("sample string");
IntPtr ip = Marshal::StringToHGlobalAnsi(s);
const char* str = static_cast<const char*>(ip.ToPointer());
Console::WriteLine("(managed) passing string...");
NativeTakesAString( str );
Marshal::FreeHGlobal( ip );
}
Beispiel: Für den Zugriff auf ANSI-Zeichenfolge erforderliche Datenmarsing
Das folgende Beispiel veranschaulicht das Datenmarsing, das für den Zugriff auf eine ANSI-Zeichenfolge in einer verwalteten Funktion erforderlich ist, die von einer nicht verwalteten Funktion aufgerufen wird. Die verwaltete Funktion kann beim Empfangen der nativen Zeichenfolge entweder direkt verwendet oder mithilfe der PtrToStringAnsi Methode in eine verwaltete Zeichenfolge konvertiert werden, wie gezeigt.
// MarshalANSI2.cpp
// compile with: /clr
#include <iostream>
#include <vcclr.h>
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma managed
void ManagedStringFunc(char* s) {
String^ ms = Marshal::PtrToStringAnsi(static_cast<IntPtr>(s));
Console::WriteLine("(managed): received '{0}'", ms);
}
#pragma unmanaged
void NativeProvidesAString() {
cout << "(native) calling managed func...\n";
ManagedStringFunc("test string");
}
#pragma managed
int main() {
NativeProvidesAString();
}