Maison >développement back-end >C++ >Comment éviter System.AccessViolationException lors du passage de chaînes entre C# et une DLL C ?

Comment éviter System.AccessViolationException lors du passage de chaînes entre C# et une DLL C ?

DDD
DDDoriginal
2025-01-02 19:01:38242parcourir

How to Avoid System.AccessViolationException When Passing Strings Between C# and a C   DLL?

Passer des chaînes entre C# et DLL C : un exemple minimal

Énoncé du problème

Malgré suivant une approche apparemment simple, le passage de chaînes entre C# et une DLL C via l'interopérabilité provoque un System.AccessViolationException. Le code dans les deux langues semble correct, ce qui crée une confusion quant à la cause première du problème.

Code C

Le code C définit une fonction, concat, qui concatène deux chaînes et renvoie le résultat. Cette fonction est marquée pour l'exportation vers la DLL à l'aide de __declspec(dllexport).

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

Code C#

En C#, le code importe la fonction concat à l'aide de DllImport. La CallingConvention est définie sur Cdecl pour correspondre à la convention C.

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

Exception et analyse

Appel de concat("a", "b") en C# une System.AccessViolationException. Cette exception indique qu'un accès mémoire non valide se produit dans le code natif.

Solution : types compatibles avec l'interopérabilité

Le coupable du problème réside dans l'utilisation de C std ::chaîne à travers la limite d'interopérabilité. C# ne peut pas créer ou gérer directement les objets std::string. Au lieu de cela, des types compatibles avec l'interopérabilité doivent être utilisés pour l'échange de données.

Types de données adaptés à l'interopérabilité

Les types d'interopérabilité appropriés incluent des tableaux de caractères terminés par un caractère nul pour transmettre des chaînes à partir de C# à C. Lors du passage de chaînes de C à C#, un StringBuilder peut être utilisé, l'appelant allouant le tampon et l'appelé y écrivant.

Code modifié

En C, la fonction concat peut être déclarée avec les paramètres char* et int pour recevoir un buffer et sa longueur.

extern "C" {
    void concat(char *str, int len)
    {
        // Concatenate strings and write to buffer
    }
}

En C#, le StringBuilder peut être utilisé.

[DllImport("...", CallingConvention = CallingConvention.Cdecl)]
static extern void concat(StringBuilder str, int len);

....

StringBuilder sb = new StringBuilder(10);
concat(sb, sb.Capacity);

En utilisant des types de chaînes compatibles avec l'interopérabilité, l'échange de chaînes entre C# et la DLL C peut être facilité efficacement.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn