Est-il possible d’appeler une fonction C à partir de C # .Net

J’ai une bibliothèque C et je veux appeler la fonction dans cette bibliothèque à partir d’une application C #. J’ai essayé de créer un wrapper C ++ / CLI sur la librairie C en ajoutant le fichier C lib comme entrée de l’éditeur de liens et en ajoutant les fichiers source en tant que dépendances supplémentaires.

Existe-t-il un meilleur moyen d’y parvenir car je ne suis pas sûr de savoir comment append une sortie C à une application c #.

Mon code C –

__declspec(dllexport) unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen); 

Mon emballage de PPC –

 long MyClass::ConnectSessionWrapper(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen) { return ConnectSession(handle, publicKey, publicKeyLen); } 

L’exemple sera, pour Linux :

1) Créez un fichier C , libtest.c avec ce contenu:

 #include  void print(const char *message) { printf("%s\\n", message); } 

C’est un simple pseudo-wrapper pour printf. Mais représente toute fonction C dans la bibliothèque que vous souhaitez appeler. Si vous avez une fonction C++ , n’oubliez pas de mettre extern C pour éviter de modifier le nom.

2) créer le fichier C#

 using System; using System.Runtime.InteropServices; public class Tester { [DllImport("libtest.so", EntryPoint="print")] static extern void print(ssortingng message); public static void Main(ssortingng[] args) { print("Hello World C# => C++"); } } 

3) Sauf si vous avez la bibliothèque libtest.so dans un chemin de bibliothèque standard comme “/ usr / lib”, vous risquez de voir une exception System.DllNotFoundException, pour corriger cela vous pouvez déplacer votre libtest.so vers / usr / lib, ou mieux encore, ajoutez simplement votre CWD au chemin de la bibliothèque: export LD_LIBRARY_PATH=pwd

crédits d’ ici

MODIFIER

Pour Windows , ce n’est pas très différent. En prenant un exemple ici , vous n’avez que votre méthode de extern "C" avec extern "C" dans votre fichier *.cpp

 extern "C" { //Note: must use __declspec(dllexport) to make (export) methods as 'public' __declspec(dllexport) void DoSomethingInC(unsigned short int ExampleParam, unsigned char AnotherExampleParam) { printf("You called method DoSomethingInC(), You passed in %d and %c\n\r", ExampleParam, AnotherExampleParam); } }//End 'extern "C"' to prevent name mangling 

alors, comstackz et dans votre fichier C #

 [DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")] public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam); 

et puis juste l’utiliser:

 using System; using System.Runtime.InteropServices; public class Tester { [DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")] public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam); public static void Main(ssortingng[] args) { ushort var1 = 2; char var2 = ''; DoSomethingInC(var1, var2); } } 

Vous pouvez appeler directement les fonctions C depuis C # en utilisant P / Invoke.
Voici une brève présentation de la création d’un répertoire C # qui entoure une DLL.

  1. Créer un nouveau projet de bibliothèque C # (je l’appellerai “Wrapper”)
  2. Ajoutez un projet Win32 à la solution, définissez le type d’application sur: DLL (je l’appellerai “CLibrary”)

    • Vous pouvez supprimer tous les autres fichiers cpp / h car nous n’en aurons pas besoin
    • Renommez le fichier CLibrary.cpp en CLibrary.c
    • Ajouter un fichier d’en-tête CLibrary.h
  3. Maintenant, nous devons configurer le projet CLibrary, cliquez dessus avec le bouton droit et accédez aux propriétés, puis sélectionnez Configuration: “Toutes les configurations”

    • Dans Propriétés de configuration> C / C ++> En-têtes précompilés, définissez les en-têtes précompilés sur: “Ne pas utiliser les en-têtes précompilés”
    • Dans la même twig C / C ++, allez à Avancé, modifiez Comstackr en: “Comstackr en code C (/ TC)”
    • Maintenant, dans la twig Linker, accédez à Général et remplacez Fichier de sortie par: “$ (SolutionDir) Wrapper \ $ (ProjectName) .dll”, cela copiera la DLL C intégrée à la racine du projet C #.

CLibrary.h

 __declspec(dllexport) unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen); 

CLibrary.c

 #include "CLibrary.h" unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen) { return 42; } 
  • Cliquez avec le bouton droit de la souris sur le projet CLibrary, construisez-le pour obtenir la DLL dans le répertoire du projet C #.
  • Cliquez avec le bouton droit sur le projet C # Wrapper, ajoutez un élément existant, ajoutez CLibrary.dll
  • Cliquez sur CLibrary.dll, accédez au volet des propriétés, définissez “Copier dans le répertoire de sortie” sur “Toujours copier”.

C’est une bonne idée de rendre le projet Wrapper dépendant de CLibrary pour que CLibrary soit construit en premier, vous pouvez le faire en cliquant avec le bouton droit sur le projet Wrapper, en allant dans “Dependencies Project” et en cochant “CLibrary”. Maintenant, pour le code wrapper réel:

ConnectSessionWrapper.cs

 using System; using System.Runtime.InteropServices; namespace Wrapper { public class ConnectSessionWrapper { [DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)] unsafe static extern UInt32 ConnectSession(UInt32 handle, char* publicKey, char publicKeyLen); public unsafe UInt32 GetConnectSession(UInt32 handle, ssortingng publicKey, char publicKeyLen) { //"Convert" ssortingng to char* char* pubKey; fixed (char* bptr = publicKey) { pubKey = (char*)bptr; } return ConnectSession(handle, pubKey, publicKeyLen); } } } 
  • La dernière chose à faire est de cliquer avec le bouton droit sur le projet Wrapper, de définir Configuration sur “Toutes les configurations” et de cocher Autoriser le code non sécurisé .
    La seule raison d’utiliser un code non sécurisé est que vous aviez un char * en paramètre et que vous deviez convertir une chaîne en pointeur fixe.

Résultat:
Test de la bibliothèque d'encapsulation dans une application console

Okay, Open VS 2010, Aller à Fichier -> Nouveau -> Projet -> Visual C ++ -> Win32 -> Projet Win32 et donnez-lui un nom (HelloWorldDll dans mon cas), puis dans la fenêtre qui suit, sous Type d’application, choisissez ‘DLL ‘ et sous Options additionnelles, choisissez ‘ Projet vide ‘ .

Maintenant, allez à l’onglet Explorateur de solutions généralement à droite de la fenêtre VS, cliquez avec le bouton droit sur Fichiers sources -> Ajouter un élément -> Fichier C ++ (.cpp) et donnez-lui un nom (HelloWorld dans mon cas).

Ensuite, dans la nouvelle classe, collez ce code:

 #include  extern "C" { __declspec(dllexport) void DisplayHelloFromDLL() { printf ("Hello from DLL !\n"); } } 

Maintenant, construisez le projet, après avoir accédé au dossier DEBUG de vos projets, vous y trouverez: HelloWorldDll.dll .

Maintenant, permet de créer notre application C # qui accédera à la DLL, Accédez à Fichier -> Nouveau -> Projet -> Visual C # -> Application Console et donnez-lui un nom (CallDllCSharp), copiez et collez ce code dans votre main:

 using System; using System.Runtime.InteropServices; ... static void Main(ssortingng[] args) { Console.WriteLine("This is C# program"); DisplayHelloFromDLL(); Console.ReadKey(); } 

et construisez le programme, maintenant que nous avons les deux nos applications construites permet de les utiliser, obtenez votre * .dll et votre .exe (bin / debug / .exe) dans le même répertoire, et exécutez la sortie de l’application devrait être

Ceci est le programme C #

Bonjour de DLL!

J’espère que cela élimine certains de vos problèmes.

Références :

  • Comment créer une bibliothèque DLL en C et l’utiliser ensuite avec C #