2010-06-02 5 views
5

Cette question peut sembler une répétition des précédentes. J'ai lu une série de messages, mais pas tout à fait clair pour ma situation.Appelez la bibliothèque C++ à partir de C#

J'ai une bibliothèque C++ qui est créée en utilisant momentics IDE. Je dois pouvoir utiliser cette bibliothèque dans un projet C#. Quelqu'un avait travaillé sur ce projet avant de me le remettre. Actuellement, il y a 2 couches pour rendre cela possible. Tout d'abord, un projet C++ inclut la bibliothèque complète avec un wrapper C++. Ce projet crée une DLL en sortie. Cette DLL C++ est ensuite envoyée à un projet C#, qui a des appels dllimport vers la DLL C++. Ce projet C# crée à nouveau un DLL. Enfin, pour utiliser la bibliothèque dans l'application C#, je dois inclure une référence à ces deux dll.

Est-ce la bonne façon de le faire fonctionner? Je pensais probablement qu'il devrait y avoir un moyen de simplifier le processus.

Quelqu'un peut-il s'il vous plaît aidez-moi avec cette question?

+0

duplication possible de [Comment appeler C++ natif à partir de C#?] (http://stackoverflow.com/questions/2211867/how-do-i-call-native-c-from-c) – Randolpho

Répondre

7

Étant donné que vous utilisez une bibliothèque C++, je suppose qu'il profite de la sémantique de C comme les classes, plutôt que d'exposer des procédures. Si tel est le cas, la façon dont cela est généralement effectué est par l'intermédiaire d'une bibliothèque d'interopérabilité C++ managée créée manuellement.

Fondamentalement, vous créez une bibliothèque C++ gérée dans Visual Studio, référencez votre bibliothèque C++ existante et créez un wrapper géré autour de vos classes C++ existantes. Vous référencez ensuite cet assembly C++ (géré) dans votre projet C# et incluez la bibliothèque C++ originale (non gérée) dans votre assembly C# juste comme un fichier qui est placé dans le répertoire de construction.

Ceci est requis car il n'existe aucun moyen de référencer des éléments tels que les classes C++ via les appels P/Invoke (DllImport).

Si votre bibliothèque de base est juste une série de fonctions, vous pouvez la référencer directement dans le projet C# via les fonctions P/Invoke. Dans tous les cas, toutes les bibliothèques mentionnées ci-dessus (pour la première, la bibliothèque C++ non gérée, l'assembly C++ managé et le projet C# ou, pour la seconde, la bibliothèque C++ non managée et le projet C#) doivent être inclus dans tout projet qui les référence. Vous ne pouvez pas lier de manière statique la bibliothèque non gérée à l'assembly géré.

+2

+1, mais je tiens à souligner que, sauf si vous utilisez .NET 1.1, "C++ géré" est maintenant appelé "C++/CLI", et il existe des * énormes * différences entre les deux. – Randolpho

+0

Aussi, je pense que vous voulez dire "vous ne pouvez pas lier dynamiquement la bibliothèque non gérée". * La liaison statiquement * est la seule façon d'utiliser la bibliothèque. – Randolpho

+0

Merci beaucoup ... Comme vous l'avez mentionné, la bibliothèque non managée a des classes et des interfaces. Ceci étant le cas, je crois que je dois avoir un wrapper C++ et un wrapper C# pour pouvoir utiliser la librairie C++ non managée dans mon application C#, non? Maintenant, l'encapsuleur C++ fait la tâche de créer l'instance des classes et d'implémenter l'interface, est-ce correct? J'ai une autre question. Est-ce le travail de la lib non administrée de fournir des fonctionnalités externes "C" et _dllexport? Actuellement, il ne le fait pas, mais je peux le mettre comme une exigence pour le prochain projet, alors je veux juste m'assurer. – Batul

0

Vous pouvez utiliser:

DllImport

class Example 
{ 
    // Use DllImport to import the Win32 MessageBox function. 
    [DllImport("user32.dll", CharSet = CharSet.Unicode)] 
    public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); 

    static void Main() 
    { 
     // Call the MessageBox function using platform invoke. 
     MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0); 
    } 
} 
2

On dirait que vous avez un emballage en trop, mais peut-être que quelqu'un est en train d'implémenter une sorte de façade ou d'ajouter des propriétés ou quelque chose du genre. La connexion de base entre managed et unmanaged sera soit DllImport des appels de fonction "plats" - pas des fonctions membres - soit des fonctions membres C++/CLI appelant un code. Si l'encapsuleur est C++/CLI, il est plus facile d'écrire (il suffit d'inclure l'en-tête pour la bibliothèque C++) et le plus facile à appeler (le code C# ajoute simplement une référence .NET) et serait donc mon premier choix. il y a une expertise C++ sur le projet.

Il semble que la personne que vous preniez en charge le fasse à la dure. S'il y a moins de 20 méthodes, je suggérerais de recommencer.

+0

Le redémarrage semblait être la meilleure solution pour moi aussi, mais une fois que j'ai commencé, quoi que je voyais, je n'ai fait que souligner que la solution actuelle était la bonne façon de le faire. Ce que je comprends de votre suggestion est également d'avoir un wrapper C++ pour gérer les classes dans la librairie C++ non managée, et ensuite utiliser les appels dllImport dans C#. Ai-je raison? – Batul

+0

Si vous ajoutez un wrapper C++/CLI, il peut vous sauver de P/Invoke (DllImport.) Fondamentalement, votre code C++/CLI peut simplement "inclure l'en-tête, lien vers la lib" pour utiliser votre code natif. Tout ce qui est 'public ref class Foo' dans le code C++/CLI peut être appelé à partir de C# sans aucun mécanisme d'interopérabilité - il suffit d'ajouter une référence et de l'utiliser. –

+0

Merci Kate. D'après ce que j'ai lu jusqu'à présent, DllImport requiert une structure plate dans la bibliothèque non gérée, c'est-à-dire aucune classe et interface. Mais ma bibliothèque non managée a des classes et des interfaces, cela signifie-t-il que je ne peux pas utiliser DllImport? Si oui, la création d'un wrapper C++/cli est la seule solution? – Batul

Questions connexes