Gewusst wie: Marshallen von COM-Zeichenfolgen mit C++-Interop
In diesem Thema wird veranschaulicht, wie ein BSTR (das grundlegende Zeichenfolgenformat, das in der COM-Programmierung bevorzugt wird) von einer verwalteten an eine nicht verwaltete Funktion übergeben werden kann und umgekehrt. Informationen zur Interoperabilität mit anderen Zeichenfolgentypen finden Sie in den folgenden Themen:
Vorgehensweise: Marshallen von Unicode-Zeichenfolgen mit C++-Interop
Vorgehensweise: Marshallen von ANSI-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. Dateien, die nur nicht verwaltete Funktionen enthalten, müssen nicht mit /clr (Common Language Runtime Compilation) kompiliert werden.
Beispiel: Übergeben von BSTR von verwalteter zu nicht verwalteter Funktion
Das folgende Beispiel veranschaulicht, wie ein BSTR (ein in der COM-Programmierung verwendetes Zeichenfolgenformat) von einer verwalteten an eine nicht verwaltete Funktion übergeben werden kann. Die aufrufende verwaltete Funktion verwendet StringToBSTR , um die Adresse einer BSTR-Darstellung des Inhalts eines .NET System.String abzurufen. Dieser Zeiger wird mithilfe von pin_ptr (C++/CLI) angeheftet, um sicherzustellen, dass die physische Adresse während eines Garbage Collection-Zyklus nicht geändert wird, während die nicht verwaltete Funktion ausgeführt wird. Der Garbage Collector darf den Speicher nicht verschieben, bis der pin_ptr (C++/CLI) den Gültigkeitsbereich überschreitet.
// MarshalBSTR1.cpp
// compile with: /clr
#define WINVER 0x0502
#define _AFXDLL
#include <afxwin.h>
#include <iostream>
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma unmanaged
void NativeTakesAString(BSTR bstr) {
printf_s("%S", bstr);
}
#pragma managed
int main() {
String^ s = "test string";
IntPtr ip = Marshal::StringToBSTR(s);
BSTR bs = static_cast<BSTR>(ip.ToPointer());
pin_ptr<BSTR> b = &bs;
NativeTakesAString( bs );
Marshal::FreeBSTR(ip);
}
Beispiel: Übergeben von BSTR von nicht verwalteter Funktion an verwaltete Funktion
Im folgenden Beispiel wird veranschaulicht, wie ein BSTR von einer nicht verwalteten Funktion an eine verwaltete Funktion übergeben werden kann. Die empfangende verwaltete Funktion kann entweder die Zeichenfolge als BSTR verwenden oder PtrToStringBSTR sie in eine String für die Verwendung mit anderen verwalteten Funktionen konvertieren. Da der Speicher, der den BSTR darstellt, für den nicht verwalteten Heap zugewiesen wird, ist keine Pinning erforderlich, da keine Garbage Collection für den nicht verwalteten Heap vorhanden ist.
// MarshalBSTR2.cpp
// compile with: /clr
#define WINVER 0x0502
#define _AFXDLL
#include <afxwin.h>
#include <iostream>
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma managed
void ManagedTakesAString(BSTR bstr) {
String^ s = Marshal::PtrToStringBSTR(static_cast<IntPtr>(bstr));
Console::WriteLine("(managed) convered BSTR to String: '{0}'", s);
}
#pragma unmanaged
void UnManagedFunc() {
BSTR bs = SysAllocString(L"test string");
printf_s("(unmanaged) passing BSTR to managed func...\n");
ManagedTakesAString(bs);
}
#pragma managed
int main() {
UnManagedFunc();
}