2009-07-31 8 views
2

J'ai un struct C++Rassemblant une struct contenant c-strings

struct UnmanagedStruct 
{ 
    char* s; 
};

et un struct C#

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

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

Répondre

0

Édition & Correction: Pour pour les valeurs d'appels p/invoke, la méthode "normal" ne fonctionne pas. J'étais tellement habitué aux comportements normaux, ref, et out liés aux paramètres de la méthode que j'ai supposé que les valeurs de retour fonctionneraient de la même manière. Voici le lien pour trouver une solution au problème de la valeur de retour:
PInvoke error when marshalling struct with a string in it

Vous ne devez utiliser un StringBuilder si vous passez la struct à la méthode C++ comme paramètre byref et la chaîne est un tampon que la méthode va changer. Pour une valeur de retour, il vous suffit de spécifier le type de chaîne, qui dans ce cas est la suivante:

struct ManagedStruct 
{ 
    [MarshalAs(UnmanagedType.Lpstr)] 
    string s; 
} 

Rememer ajouter une propriété pour exposer la chaîne, puisque s est ici privée (qui est OK, les champs doivent être privé).

+2

Il n'y a rien de mal à rendre les champs public dans les structures qui sont utilisées uniquement à des fins P/Invoke. Tous les accesseurs seraient triviaux de toute façon, et cela ne changera jamais à l'avenir, alors pourquoi écrire plus de code? –

+0

J'ai essayé, mais je continue à me signature de type de méthode n'est pas compatible Pinvoke – DevDevDev

+0

lecture Microsoft aide il dit « chaînes ANSI doivent être marshalés au moyen d'un IntPtr et transmis comme un tableau d'octets. » – DevDevDev