Comment : marshaler des chaînes COM à l'aide de l'interopérabilité C++

Cette rubrique montre comment un BSTR (format de chaîne de base favorisé dans la programmation COM) peut être passé d'une fonction managée à une fonction non managée, et inversement. Pour interagir avec d'autres types de chaînes, consultez les rubriques suivantes :

Les exemples de code suivants utilisent les directives #pragma managed, unmanaged pour implémenter des fonctions managées et non managées dans le même fichier, mais ces fonctions interagissent de la même manière si elles sont définies dans des fichiers séparés. Les fichiers qui contiennent uniquement des fonctions non managées ne doivent pas être compilés avec /clr (Compilation pour le Common Language Runtime).

Exemple

L'exemple suivant montre comment un BSTR (format de chaîne utilisé dans la programmation COM) peut être passé d'une fonction managée à une fonction non managée. La fonction managée appelante utilise StringToBSTR pour obtenir l'adresse d'une représentation BSTR du contenu d'un .NET System.String. Ce pointeur est épinglé à l'aide de pin_ptr pour vérifier que son adresse physique n'est pas modifiée pendant un cycle de garbage collection au cours de l'exécution de la fonction non managée. Le garbage collector n'est pas autorisé à déplacer la mémoire aussi longtemps que pin_ptr n'est pas hors de portée.

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

L'exemple suivant montre comment un BSTR peut être passé d'une fonction non managée à une fonction non managée. La fonction managée réceptrice peut utiliser la chaîne en tant que BSTR ou utiliser PtrToStringBSTR pour la convertir en String en vue d'une utilisation avec d'autres fonctions managées. Comme la mémoire représentant le BSTR est allouée sur le tas non managé, aucun épinglage n'est nécessaire, car il n'existe aucun garbage collection sur le tas non managé.

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

Voir aussi

Référence

Utilisation de l'interopérabilité C++ (PInvoke implicite)