65 votes

Comment dois-je appeler natif C++ C#?

J'ai une classe implémentée en C++, qui est responsable pour le calcul numérique du programme et d'une interface à l'aide de WPF. J'processus de l'entrée avec C# mais alors, comment puis-je utiliser ma classe C++?

J'ai vu quelques commentaires au sujet de faire un wrapper C++ managé classe d'interagir avec elle, mais je ne sais pas par où commencer. Je ne sais pas comment je vais compiler le long avec tous le autre code. Je ne peux pas vraiment trouver un tutoriel sur le présent, et le truc de google montre sur le C++ ne semble pas vraiment utile.

N'importe quoi pour m'aider? Cela ne semble pas déraisonnable de moi.

EDIT Essayé m3rLinEz solution, mais c'est de me donner un BadImageFormatException, je pense que c'est parce que la DLL n'est pas générée. J'ai tout fait comme dit, je ne sais pas ce qui s'est passé. Des idées?

57voto

Gant Points 9920

Avez-vous de prendre un coup d'oeil sur le C++/CLI?

Laissez-moi vous donner un bref exemple. Voici le fichier source à partir d'un Visual C++ -> CLR -> projet de Bibliothèque de classes. Il fondamentalement obtenir un nom d'utilisateur Windows et le retourner.

Veuillez noter que, afin d'obtenir cette compilé, vous devez aller dans les paramètres de projet et de la marque "Dépendances Supplémentaires" comme "Hérite de l'objet parent" parce que nous sommes à l'aide de ces Fenêtres libs (kernel32.lib, user32.lib, ..)

// CSCPP.h

#pragma once

#include "windows.h"

using namespace System;

namespace CSCPP {

    public ref class Class1
    {
        // TODO: Add your methods for this class here.
    public:
        String^ GetText(){
            WCHAR acUserName[100];
            DWORD nUserName = sizeof(acUserName);
            if (GetUserName(acUserName, &nUserName)) {
                String^ name = gcnew String(acUserName);
                return String::Format("Hello {0} !", name);
            }else{
                return gcnew String("Error!");
            }
        }
    };
}

Créer un nouveau projet C# et ajouter une référence à notre première C++/CLI Classe de Bibliothèque de projet. Et puis d'appeler la méthode d'instance.

namespace CSTester
{
    class Program
    {
        static void Main(string[] args)
        {
            CSCPP.Class1 instance = new CSCPP.Class1();
            Console.WriteLine(instance.GetText());
        }
    }
}

Cela a donné le résultat suivant sur ma machine:

Bonjour m3rlinez !

C++/CLI est essentiellement géré extension de C++ standard. Il vous permet d'utiliser des classes CLR et les types de données en C++/CLI projet et de faire connaître ce langage managé. Vous pouvez créé un wrapper géré pour votre ancien de la bibliothèque C++ à l'aide de ce. Il y a quelques bizarre syntaxes String^ pour définir le type de référence à CLR Chaîne. - Je trouver des "Quick C++/CLI - Apprendre le C++/CLI en moins de 10 minutes" pour être utile ici.

9voto

Arve Points 3665

Il y a au moins trois façons d'appeler du code non managé de gérer dans le même processus:

  1. C++/CLI
  2. Appel De Plate-Forme
  3. Enveloppez votre C++ dans un objet COM

Au travail, nous utilisons C++/CLI pour cela, il semble fonctionner.

4voto

Ash Points 31541

Je voudrais créer un standard (non COM/Géré) Bibliothèque de liens Dynamiques comme décrit ici et ensuite utiliser l' attribut DllImport (platform invoke) dans le code c# pour accéder aux fonctions exportées.

Le point clé de cet article:

Note de __declspec(dllexport) modificateur dans les déclarations de méthode dans ce code. Ces modificateurs de permettre à l' méthode à être exportées par la DLL afin qu'il peut être utilisé par d'autres des applications. Pour plus d'informations, voir dllexport, dllimport.

C'est un poids léger alternative à une réelle interopérabilité COM wrapper et évite les problèmes tels que l'inscription, etc (la DLL peut simplement être placé dans le répertoire de l'application) .

Une autre alternative est qu'Il Fonctionne, tout Simplement (IJW). C'est probablement un meilleur choix si vous avez réussi à du code C++ et de la nécessité d'y accéder à partir d'autres .NET languages. Mais ce n'est qu'une option si vous êtes en mesure/heureux pour convertir votre le C++ pour le C++.

4voto

Igor Zevaka Points 32586

Je voudrais rester à l'écart de P/Invoke que c'est assez lent par rapport à IJW (Il Fonctionne, tout Simplement). Ce dernier vous permet facilement d'associer gérés et non gérés et non c++. Tout ce que vous avez à faire est de créer un managed c++ assemblée, écrire une classe managée qui est visible à partir de c# et de l'appeler le code non managé.

Euh... OK. J'étais sous l'impression que P/Invoke appels ont été plus lents qui ils sont inherintly pas. Cependant, en ayant un contrôle explicite sur la composition des trains, vous pouvez rendre votre C++/CLI version de mieux performer dans un grand nombre de cas.

Ici Microsoft, qui est l'article sur les deux mécanismes:

http://msdn.microsoft.com/en-us/library/ms235282.aspx

Avantages de IJW

  • Il n'est pas nécessaire d'écrire attribut DLLImport déclarations pour les non géré Api utilise le programme. Juste inclure le fichier d'en-tête et le lien avec la bibliothèque d'importation.
  • Le IJW mécanisme est légèrement plus rapide (par exemple, la IJW talons de ne pas besoin de vérifier la nécessité de pin ou copie les éléments de données parce que c'est fait explicitement par le développeur).
  • Il illustre clairement les problèmes de performances. Dans ce cas, le fait que vous êtes à la traduction de l'Unicode chaîne d'une chaîne ANSI et que vous avoir un serviteur de l'allocation de mémoire et la désallocation. Dans ce cas, un développeur de l'écriture du code à l'aide de IJW se rendrait compte que l'appel _putws et à l'aide de PtrToStringChars serait mieux pour la performance.
  • Si vous appelez de nombreuses Api non gérées en utilisant les mêmes données, le marshaling une fois et le dépassement de la conversion de paramètres de copie est beaucoup plus efficace que de la re-marshaling chaque fois.

Il y a des avantages esthétiques ainsi:

  • C# à quoi ressemble le code C# code sans interop y étrangeté.
  • Vous n'avez pas à définir DLLImport d'attribut, vous n'avez pas besoin de définir des structures de données (avec un p/invoke attributs spécifiques) qui pourrait ressembler à ceci:

    [StructLayout(LayoutKind.Séquentielle, CharSet = Jeu De Caractères.Ansi)] public structure DevMode { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string dmDeviceName; }

  • Vous n'avez pas à convertir tous les paramètres de types primitifs dans leur .NET homologues (il y a le tableau sur cette page qui indique les types gérés carte de types non gérés).
  • Vous arrivez à travailler avec le C++/CLI qui est vraiment amusant d'apprendre et il est vraiment poli. Il est venu un long chemin depuis VS 2003 et est maintenant complet .NET de la langue. La documentation de Microsoft pour il est assez bon, comme tous les IJW de l'information.
  • Faire C++ interop en C++/CLI se sent très naturel, par opposition à C#. C'est complètement subjectif, mais je préférerais de beaucoup préfèrent faire de la chaîne de triage en C++ qui n' Marshal.PtrToString(ptr).
  • Si exposer une API vous auriez probablement souhaitez envelopper tous les P/Invoke choses dans une autre couche, de sorte que vous n'avez pas à traiter avec P/Invoke la laideur. De cette façon, vous avez les frais généraux de tous les le triage ET le C# de la couche autour d'elle. Avec le C++/CLI sur la formation et l'interopérabilité de l'abstraction en un seul endroit, et vous pouvez choisir combien de triage dont vous avez besoin.

À mon humble avis, si vous appelez une fonction bizarre dans le SDK de Windows, allez-y avec P/Invoke. Si vous êtes exposant un modérément complexes API C++ pour la gestion du monde, certainement le C++/CLI.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X