J'ai une bibliothèque C et je veux appeler une fonction dans cette bibliothèque à partir de l'application C #. J'ai essayé de créer un wrapper C++/CLI sur la bibliothèque 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 sais pas comment ajouter la sortie C à l'application c #.
Mon code C -
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
Mon emballage CPP -
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 <stdio.h>
void print(const char *message)
{
printf("%s\\n", message);
}
C’est un simple pseudo-wrapper pour printf. Mais représente n'importe quelle fonction C
de la bibliothèque que vous souhaitez appeler. Si tu as un C++
fonction n'oubliez pas de mettre extern C
pour éviter de modifier le nom.
2) créez le C#
fichier
using System;
using System.Runtime.InteropServices;
public class Tester
{
[DllImport("libtest.so", EntryPoint="print")]
static extern void print(string message);
public static void Main(string[] 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 verrez probablement une System.DllNotFoundException, pour résoudre ce problème, 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 de ici
[~ # ~] modifier [~ # ~]
Pour Windows, ce n'est pas très différent. Prenant un exemple de ici , vous n'avez qu'à enfermer dans votre *.cpp
fichier votre méthode avec extern "C"
Quelque chose comme
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
puis, compilez et dans votre fichier C # faites
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]
public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);
puis utilisez-le:
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(string[] args)
{
ushort var1 = 2;
char var2 = '';
DoSomethingInC(var1, var2);
}
}
MISE À JOUR - 22 février 2019: Puisque cette réponse a reçu pas mal de votes positifs, j'ai décidé de la mettre à jour avec une meilleure façon d'appeler la méthode C. Auparavant, j'avais suggéré d'utiliser le code unsafe
, mais la manière sûre et correcte consiste à utiliser l'attribut MarshalAs
pour convertir un .NET string
en char*
. De plus, dans VS2017, il n'y a plus de projet Win32, vous devrez probablement créer une DLL Visual C++ ou un projet vide et le modifier. Merci!
Vous pouvez appeler directement les fonctions C à partir de C # à l'aide de P/Invoke.
Voici un petit guide pratique sur la création d'une bibliothèque C # qui s'enroule autour d'une DLL C.
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, cliquer dessus avec le bouton droit et aller dans les propriétés, puis sélectionner 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 "Project Dependencies" et en cochant "CLibrary". Maintenant, pour le code de wrapper réel:
ConnectSessionWrapper.cs
using System.Runtime.InteropServices;
namespace Wrapper
{
public class ConnectSessionWrapper
{
[DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern uint ConnectSession(uint handle,
[MarshalAs(UnmanagedType.LPStr)] string publicKey,
char publicKeyLen);
public uint GetConnectSession(uint handle,
string publicKey,
char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}
}
}
Maintenant, appelez simplement GetConnectSession
, et il devrait retourner 42
.
Résultat:
D'accord, ouvrez VS 2010, Goto Fichier -> Nouveau -> Projet -> Visual C++ -> Win32 -> Projet Win32 et donnez-lui un nom (HelloWorldDll dans mon cas), puis dans le fenêtre qui suit sous Type d'application choisissez 'DLL' et sous Options supplémentaires choisissez 'Projet vide' .
Maintenant, allez dans votre Explorateur de solutions onglet généralement à droite de la fenêtre VS, faites un clic droit Fichiers source -> Ajouter un élément -> Fichier C++ (.cpp) et donnez un nom (HelloWorld dans mon cas)
Ensuite, dans la nouvelle classe, collez ce code:
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf ("Hello from DLL !\n");
}
}
Maintenant Build le projet, après avoir accédé à vos projets [~ # ~] déboguer le dossier [~ # ~] et là vous devriez trouver: HelloWorldDll.dll .
Maintenant, créons notre application C # qui accédera à la dll, Goto Fichier -> Nouveau -> Projet -> Visual C # -> Application console et donnez-lui un nom (CallDllCSharp), maintenant copiez et collez ce code dans votre main:
using System;
using System.Runtime.InteropServices;
...
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
DisplayHelloFromDLL();
Console.ReadKey();
}
et construisez le programme, maintenant que nos deux applications sont construites, utilisons-les, récupérez votre * .dll et votre . exe (bin/debug /. exe) dans le même répertoire, et exécutez la sortie de l'application doit être
Ceci est le programme C #
Bonjour de DLL!
J'espère que cela clarifie certains de vos problèmes.
Références :