Gewusst wie: Marshallen von COM-Zeichenfolgen mit C++-Interop
In diesem Thema wird beschrieben, wie BSTR (das bei der COM-Programmierung bevorzugte grundlegende Zeichenfolgenformat) von einer verwalteten an eine nicht verwaltete Funktion und umgekehrt übergeben werden kann.Informationen zur Interoperation mit anderen Zeichenfolgentypen finden Sie in den folgenden Themen:
Gewusst wie: Marshallen von Unicode-Zeichenfolgen mit C++-Interop
Gewusst wie: Marshallen von ANSI-Zeichenfolgen mit C++-Interop
In den folgenden Codebeispielen werden die verwaltet, nicht verwaltet-#pragma-Direktiven verwendet, um verwaltete und nicht verwaltete Funktionen in derselben Datei zu implementieren. Diese Funktionen arbeiten jedoch auf dieselbe Weise zusammen, wenn sie in separaten Dateien definiert werden.Dateien, die ausschließlich nicht verwaltete Funktionen enthalten, müssen nicht mit /clr (Common Language Runtime-Kompilierung) kompiliert werden.
Beispiel
Das folgende Beispiel zeigt, wie 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 zum Abrufen der Adresse einer BSTR-Darstellung der Inhalte eines .NET-System.String.Dieser Zeiger wird mit pin_ptr fixiert, um sicherzustellen, dass seine physische Adresse während eines Garbage Collection-Zyklus bei Ausführung einer nicht verwalteten Funktion nicht geändert wird.Der Garbage Collector kann so lange keinen Arbeitsspeicher verschieben, bis pin_ptr den Bereich verlassen hat.
// 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);
}
Das folgende Beispiel zeigt, wie eine BSTR-Zeichenfolge von einer nicht verwalteten an eine verwaltete Funktion übergeben werden kann.Die empfangende verwaltete Funktion kann entweder die Zeichenfolge als BSTR in verwenden oder PtrToStringBSTR verwenden, um es zu String für die Verwendung mit anderen verwalteten Funktionen zu konvertieren.Da der BSTR darstellende Arbeitsspeicher auf dem nicht verwalteten Heap belegt ist, ist keine Fixierung erforderlich, denn auf dem nicht verwalteten Heap erfolgt keine Garbage Collection.
// 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();
}