Comment passer un argument de chaîne de C ++ à une DLL C # gérée

J’écris un programme C ++ qui doit appeler une DLL écrite en C #. J’ai suivi ces instructions pour créer ma DLL C # et la relier depuis mon C ++.

https://support.microsoft.com/en-us/kb/828736

J’ai une fonction C # qui prend une chaîne en argument. Comment passer une chaîne de C ++ dans mon C #?

Je ne pouvais pas trouver une réponse concise à cette question, alors je mets ma solution ici dans l’espoir que cela aide quelqu’un à l’avenir.

TL; DR: vous devez utiliser un BSTR pour passer des chaînes entre C # et C ++.

Voici comment je l’ai fait.

Code C #

Voici un exemple de mon code C #. Quelques points à noter:

  • Toute fonction que vous voulez pouvoir appeler à partir du C ++ Doit être détaillée dans la section interface .
  • Notez la façon dont je déclare l’argument ssortingngToPrint fois dans l’interface et dans la définition de la fonction. Préfacer une ssortingng avec [MarshalAs(UnmanagedType.BStr)] est crucial.
  • Une fois dans la fonction, vous pouvez utiliser l’argument de ssortingng comme s’il s’agissait d’une chaîne normale. Vous n’avez pas besoin de convertir BSTR en C # comme vous le faites en C ++. Plus à ce sujet ci-dessous.

Fichier .CS

 //Reference where I got all this: //https://support.microsoft.com/en-us/kb/828736 // Class1.cs // A simple managed DLL that contains a method to add two numbers. using System; using System.Runtime.InteropServices; namespace ManagedDLL { // Interface declaration. public interface ICalculator { //Test functions int Add(int Number1, int Number2); int ReturnAge(); ssortingng SsortingngTest(); void PrintASsortingng([MarshalAs(UnmanagedType.BStr)] ssortingng ssortingngToPrint); }; // Interface implementation. public class ManagedClass : ICalculator { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Test functions public int Add(int Number1, int Number2) { return Number1 + Number2; } public int ReturnAge() { return 35; } public ssortingng SsortingngTest() { return "Can you hear me now?"; } public void PrintASsortingng([MarshalAs(UnmanagedType.BStr)] ssortingng ssortingngToPrint) { Console.WriteLine("Trying to print a BSTR in C#"); Console.WriteLine(ssortingngToPrint); Console.WriteLine("Done printing"); } } } 

Code C ++

Quelques points à noter dans le C ++:

  • L’appel #import dans l’en-tête. C’est ici que vous indiquez au C ++ comment trouver votre bibliothèque C #. Ceci est mentionné dans le tutoriel auquel je fais référence dans la question.
  • Si vous avez une valeur de retour dans l’une de vos fonctions C #, elle ne sera pas renvoyée au C ++. Au lieu de cela, vous devrez inclure un pointeur sur une variable C ++ en tant que paramètre lorsque vous effectuez l’appel. Voir la fonction AddTest() pour un exemple.
  • Les chaînes doivent être passées au C # en tant BSTR variables de type BSTR . Il est assez facile de convertir un std::ssortingng en un BSTR , j’ai des fonctions pour effectuer la conversion dans les deux sens.

header de fichier

 //csLink.h #include  #include  #include  #import "path/to/C#/dll.tlb" raw_interfaces_only using namespace std; namespace Sample{ class CSLink { public: CSLink(); //Test functions int AddTest(int i1, int i2); int AgeTest(); ssortingng SsortingngTestCall(); void ssortingngArgTest(ssortingng s); private: ICalculatorPtr pCalc; long lResult; ssortingng convertBSTR(BSTR *s); BSTR convertBSTR(ssortingng s); }; } 

Fichier source

 //csLink.cpp #include "stdafx.h" #include "csLink.h" using namespace std; namespace Sample{ //Constructor CSLink::CSLink(){ cout << "You have created a CS Link" << endl; //https://support.microsoft.com/en-us/kb/828736 HRESULT hr = CoInitialize(NULL); pCalc = ICalculatorPtr(__uuidof(ManagedClass)); lResult = 0; } //Test functions int CSLink::AddTest(int i1, int i2){ cout << "you are adding " << i1 << " and " << i2 << endl; pCalc->Add(i1, i2, &lResult); cout << "The result should have been " << i1 + i2 << " and it was " << lResult << endl; return 0; } int CSLink::AgeTest(){ cout << "Trying to get my age" << endl; pCalc->ReturnAge(&lResult); return lResult; } ssortingng CSLink::SsortingngTestCall(){ BSTR s; pCalc->SsortingngTest(&s); return convertBSTR(&s); } void CSLink::ssortingngArgTest(ssortingng s) { //References I used figuring this all out: //http://stackoverflow.com/questions/28061637/how-to-pass-ssortingng-parameters-between-c-and-c //https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasatsortingbute(v=vs.110).aspx //http://forums.codeguru.com/showthread.php?193852-How-to-convert-ssortingng-to-wssortingng //http://stackoverflow.com/questions/6284524/bstr-to-stdssortingng-stdwssortingng-and-vice-versa BSTR bSTR = convertBSTR(s); cout << "~~~~~~~~~~~~~~~~~~~~~~~" << endl; cout << "Testing conversion: " << convertBSTR(&bSTR) << "|end test" << endl; pCalc->PrintASsortingng(bSTR); cout << "~~~~~~~~~~~~~~~~~~~~~~~" << endl; } //Utility functions string CSLink::convertBSTR(BSTR *s){ if (*s == nullptr){ return "NULL STRING"; } else{ wstring ws(*s, SysStringLen(*s)); string ss(ws.begin(), ws.end()); return ss; } } BSTR CSLink::convertBSTR(string s){ wstring wStr = wstring(s.length(), L' '); copy(s.begin(), s.end(), wStr.begin()); return SysAllocStringLen(wStr.data(), wStr.size()); } } 

C'est à peu près ça. Commentaire avec des questions, je ferai de mon mieux pour répondre.