2010-06-10 6 views
1

Le .net qui suit en code natif C ne fonctionne pas, des idéesPourquoi cette P/Invoke explicite ne fonctionne pas?

extern "C" { 
    TRADITIONALDLL_API int TestStrRef(__inout char* c) { 
    int rc = strlen(c); 
    std::cout << "the input to TestStrRef is: >>" << c << "<<" ; 
    c = "This is from the C code "; 
    return rc; 
    } 
} 

[DllImport("MyDll.dll", SetLastError = true)] 
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s); 
String abc = "InOut string"; 
TestStrRef(ref abc); 

À ce stade Console.WriteLine (abc) doit imprimer les « Ceci est du code C », mais n'a pas, des idées sur la Qu'est-ce qui ne va pas ?

Pour votre information - j'ai une autre fonction de test ne pas utiliser la chaîne de type ref, il fonctionne très bien

+1

faire fonctionner dans C en premier. –

+0

Natif C - il fait C .net - ne sais pas :( – Kumar

Répondre

5

Votre code erroné à côté C aussi. __inout annotation indique simplement au compilateur que vous pouvez changer le tampon vers lequel pointe l'argument "c". Mais pointeur lui-même situé dans la pile et ne retourne pas à l'appelant si vous avez modifié l'argument "c". Votre déclaration peut ressembler à:

extern "C" { 
    TRADITIONALDLL_API int TestStrRef(__inout char** c) { 
    int rc = strlen(*c); 
    std::cout << "the input to TestStrRef is: >>" << *c << "<<" ; 
    *c = "This is from the C code "; 
    return rc; 
    } 
} 

Et côté C#:

[DllImport("MyDll.dll", SetLastError = true)] 
static extern int TestStrRef(ref IntPtr c); 

{ 
    String abc = "InOut string"; 
    IntPtr ptrOrig = Marshal.StringToHGlobalAnsi(abc)   
    IntPtr ptr = ptrOrig; // Because IntPtr is structure, ptr contains copy of ptrOrig 
    int len = TestStrRef(ref ptr); 
    Marshal.FreeHGlobal(ptrOrig); // You need to free memory located to abc' native copy 
    string newAbc = Marshal.PtrToStringAnsi(ptr); 
    // You cannot free memory pointed by ptr, because it pointed to literal string located in dll code. 
} 
0

Est-ce que ce travail pour vous? Fondamentalement, il suffit d'ajouter CallingConvention = CallingConvention.Cdecl à l'instruction DllImport. Vous pouvez également spécifier le CharSet (par exemple: charset: = CharSet.Unicode)

[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] 
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s); 
+0

Pourquoi la convention d'appel importe? L'appel de la méthode (s) fonctionne déjà pour l'OP –

+0

Quoi qu'il en soit, j'ai essayé, cela n'a pas fonctionné! – Kumar

Questions connexes