Passando le stringhe da C # a C ++ DLL e ritorno – esempio minimo

Sto cercando di rendere l’esempio assolutamente semplice e minimo di come passare le stringhe da e verso una DLL C ++ in C #.

Il mio C ++ si presenta così:

using std::string; extern "C" { string concat(string a, string b){ return a + b; } } 

Con un colpo di testa come

 using std::string; extern "C" { // Returns a + b __declspec(dllexport) string concat(string a, string b); } 

Il mio C # è

 [DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)] static extern string concat(string a, string b); } 

E lo chiamo con: Console.WriteLine (concat (“a”, “b”));

Ma questo dà un System.AccessViolationException. Sembra che sia la cosa più banale da affrontare, ma sono completamente bloccato su di esso. Quando ho provato a fare un esperimento simile con una funzione “Aggiungi” che ha richiesto due doppi e restituito un doppio, non ho avuto problemi.

Non è ansible passare una std::string C ++ attraverso un limite di interoperabilità. Non è ansible crearne uno nel codice C #. Quindi il tuo codice non può mai funzionare.

È necessario utilizzare i tipi interoperabili al limite di interoperabilità. Ad esempio, matrici di caratteri con terminazione nulla. Funziona bene quando assegni e dealloculi la memoria nello stesso modulo. Quindi, è abbastanza semplice quando si passano dati da C # a C ++.

C ++

 void foo(const char *str) { // do something with str } 

C #

 [DllImport("...", CallingConvention = CallingConvention.Cdecl) static extern void foo(string str); .... foo("bar"); 

Nella direzione opposta normalmente ci si aspetta che il chiamante assegni il buffer, nel quale il callee può scrivere:

C ++

 void foo(char *str, int len) { // write no more than len characters into str } 

C #

 [DllImport("...", CallingConvention = CallingConvention.Cdecl) static extern void foo(StringBuilder str, int len); .... StringBuilder sb = new StringBuilder(10); foo(sb, sb.Capacity);