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:

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();
}

Siehe auch

Verwenden von C++-Interop (implizites PInvoke)