2009-03-02 12 views
4

J'ai un code C standard ANSI qui fait autorité. Cela signifie que même si j'ai la source, je ne peux pas traduire dans une autre langue ni modifier les arguments d'appel, car ces actions invalideraient l'autorité. Il y a plus de 150 fonctions.Obtention de fonctions C++ non gérées à partir de C#

Je peux faire des changements, tels que le changement des noms de fichiers de .c .CPP afin qu'il compile en utilisant Visual Studio 2009 de compilateur C++, que je l'ai fait. Les directives du compilateur et autres peuvent également être ajoutées. Je peux aussi passer par une couche d'emballage, si nécessaire.

Une autre restriction est ma société ne pas veux que je l'utilise dans tout code C# le mot clé dangereux .

Je dois obtenir ces fonctions à partir d'un programme C#.

Une fonction C/C++ typique ressemble à ceci:
double SomeFunction(double a, double[3] vec, double[3][3] mat);
Si le contenu du tableau sont parfois entrée, parfois sortie, et rarement les deux.

J'ai d'abord essayé de créer une DLL non managée (avec les fonctions marquées Extern C). Les fonctions avec seulement des arguments simples (int, double) fonctionnaient bien, mais je ne pouvais pas déterminer comment marshal les tableaux. (En fait, j'ai trouvé un exemple de code, mais il était extrêmement complexe et déraisonnable de dupliquer 150 fois.)

J'ai ensuite essayé deux projets dans la même solution, l'un en C++ et l'autre en C#. Dans le projet C++, j'ai créé une fonction gérée qui vient d'appeler la fonction d'origine qui a été marquée comme non gérée. C'était extrêmement propre et simple, et encore une fois, les arguments simples ont bien fonctionné. Mais pour les tableaux, je ne pouvais pas trouver comment faire correspondre les types d'arguments à travers la frontière C# à C++:
Argument '2': cannot convert from 'double[]' to 'double*'
(et comme mentionné ci-dessus, je ne peux pas utiliser dangereux pour obtenir un pointeur).

Certainement ce que j'essaie de faire doit être possible.
Quel est le meilleur moyen d'accéder à ces fonctions?
(Exemple de code utilisant la fonction ci-dessus serait vraiment cool.)

Répondre

4

Exemple C/implémentation C++:

extern "C" __declspec(dllexport) 
double SomeFunction(double a, double vec[3], double mat[3][3]) { 
    double sum = a; 
    for (int ix = 0; ix < 3; ++ix) { 
    sum += vec[ix]; 
    for (int iy = 0; iy < 3; ++iy) { 
     sum += mat[ix][iy]; 
    } 
    } 
    return sum; 
} 

Exemple d'utilisation C#:

private void Form1_Load(object sender, EventArgs e) { 
    double[] vec = new double[3]; 
    double[,] mat = new double[3, 3]; 
    for (int ix = 0; ix < 3; ++ix) { 
    vec[ix] = ix; 
    for (int iy = 0; iy < 3; ++iy) { 
     mat[ix, iy] = (ix + 1) * iy; 
    } 
    } 
    double sum = SomeFunction(1, vec, mat); 
} 
[System.Runtime.InteropServices.DllImport("cpptemp8.dll")] 
private static extern double SomeFunction(double a, double[] vec, double[,] mat); 
+0

Ah, je vous remercie! La clé de ce problème était qu'en C++ le tableau est déclaré comme double [] [], mais en C# comme double [,]. Bien que la première soit une syntaxe C# légale, elle ne représente pas la même organisation interne. Sans cette idée clé, cela ne fonctionnerait pas. –

1

Si vous ne pouvez pas obtenir la solution extern et P/Invoke pour fonctionner, un wrapper est probablement votre meilleur pari. Créez une DLL C++ gérée qui utilise du code managé et non managé. Ajoutez une classe .NET à cette DLL qui est juste un wrapper fin sur les fonctions de votre DLL C. Votre code C# peut appeler la classe C++ .NET, qui à son tour transmettra les fonctions C.

De cette façon, vous pouvez écrire la traduction entre le code .NET et non géré vous, au lieu de compter sur le temps d'exécution pour le faire pour vous.

0

utilisation rasade, il va générer votre PInvoke pour vous

Questions connexes