2009-08-03 6 views
3

J'ai un struct C++erreur PInvoke lors struct marshalling avec une chaîne en elle

struct UnmanagedStruct 
{ 
    char* s; 
    // Other members 
};

et un struct C#

struct ManagedStruct { 
    [MarshalAs(UnmanagedType.LPStr)] 
    string s; 
    // Other members 
}

la bibliothèque C++ expose

extern "C" UnmanagedStruct __declspec(dllexport) foo(char* input); 

Et il est importé comme

[DllImport("SomeDLL.dll", CharSet = CharSet.Ansi)] 
    static extern ManagedStruct foo(string input); 

Cependant quand j'appelle cette fonction je reçois

MarshalDirectiveException était non gérée

signature de type de méthode n'est pas PInvoke compatible. Le fait est que cet appel de fonction fonctionne si je supprime le char * s et la chaîne s des structs.

Répondre

4

Pour ce type de scénario, n'utilisez pas de chaîne directement. Au lieu de cela, changez le type en valeur IntPtr et utilisez Marshal.PtrToStringAuto/Ansi/Uni selon le cas. Dans ce cas, puisque votre code natif utilise char*, PtrToStringAnsi est le meilleur choix.

struct ManagedStruct { 
    IntPtr s; 
    public string sAsString { get { return Marshal.PtrToStringAnsi(s); } } 
} 
+0

Pourquoi est-ce que je dois faire cela? J'ai posé cette question tout à l'heure et les gens disaient tous que cela «fonctionnerait». – DevDevDev

+0

@SteveM, les chaînes + PInvoke = difficile. Les chaînes fonctionnent juste dans beaucoup de scénarios mais échouent juste dans beaucoup d'autres :). Les chaînes comme champs d'une structure sont particulièrement difficiles car il y a un énorme problème de gestion de la mémoire. En particulier, que devrait faire le CLR avec la mémoire utilisée pour créer la chaîne gérée? Devrait-il le libérer ou ne rien faire? En général, si le CLR voit quelque chose comme ça, il supposera qu'il doit libérer les données et finira par appeler CoTaskMemFree sur la valeur qui est probablement fausse dans votre scénario. – JaredPar

+0

(suite). En général, si vous êtes toujours confus sur la façon dont une chaîne doit être rassemblée (et ce n'est pas un tableau en ligne), utilisez IntPtr et la main marshal la chaîne. Cela a une bien meilleure chance de travailler – JaredPar

Questions connexes