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.
Ajoutez un projet Win32 à la solution, définissez le type d’application sur: DLL (je l’appellerai “CLibrary”)
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”
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; }
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); } } }
Résultat:
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 :