68 votes

Compilez une DLL en C / C ++, puis appelez-la à partir d'un autre programme.

Je veux faire un simple, simple DLL qui exporte une ou deux fonctions, puis essayez de l'appeler à partir d'un autre programme... Partout où j'ai regardé jusqu'à présent, est pour compliqué les choses, les différentes façons de lier les choses ensemble, des problèmes bizarres que je n'ai même pas commencé à réaliser existent encore... je veux juste obtenir commencé, en faisant quelque chose comme ça:

Faire une DLL qui exporte à certaines fonctions, comme,

int add2(int num){
   return num + 2;
}

int mult(int num1, int num2){
   int product;
   product = num1 * num2;
   return product;
}

Je compile avec MinGW, j'aimerais le faire en C, mais si il y a de véritables différences de le faire en C++, j'aimerais savoir ceux aussi. Je veux savoir comment charger les DLL dans un autre C (et C++) du programme, et ensuite appeler ces fonctions à partir d'elle. Mon but ici, après avoir joué avec Dll pour un peu, est de faire une VB front-end pour le C(++) du code, par le chargement des Dll en visual basic (j'ai visual studio 6, je veux juste faire certaines formes et manifestations pour les objets sur les formes, où l'appel de la DLL).

J'ai besoin de savoir comment appeler gcc (/g++) de manière à créer une DLL, mais aussi la façon d'écrire (/générer un fichier d'exportation... et ce que je peux/ne peux pas le faire dans une DLL (comme, puis-je prendre des arguments par pointeur/référence de la VB front-end? Peut l'appel de la DLL théorique de la fonction dans le front-end? Ou prendre un "pointeur de fonction" (je ne sais même pas si c'est possible) à partir de VB et de l'appeler?) Je suis assez certain que je ne peux pas passer d'une variante à la DLL...mais c'est tout ce que je sais vraiment.

mise à jour

Ok, j'ai compris comment le compiler avec gcc, pour faire de la dll, j'ai couru

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a

et puis j'ai eu un autre programme de la charge et de tester les fonctions, et il a travaillé beaucoup, merci beaucoup pour les conseils, mais j'ai essayé de le charger avec VB6, comme ceci

Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer

alors je viens d'appeler add2(texte1.texte) à partir d'un formulaire, mais il m'a donné une erreur à l'exécution:

"Impossible de trouver le DLL point d'entrée dans add2 C:\c\dll\mydll.dll"

c'est le code que j'ai compilé pour la DLL:

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

EXPORT int __stdcall add2(int num){
  return num + 2;
}

EXPORT int __stdcall mul(int num1, int num2){
  return num1 * num2;
}

l'appelant depuis le programme C comme cela a fonctionné, si:

#include<stdio.h>
#include<windows.h>

int main(){

  HANDLE ldll;
  int (*add2)(int);
  int (*mul)(int,int);

  ldll = LoadLibrary("mydll.dll");
  if(ldll>(void*)HINSTANCE_ERROR){
    add2 = GetProcAddress(ldll, "add2");
    mul = GetProcAddress(ldll, "mul");
    printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
  } else {
    printf("ERROR.");
  }

}

des idées?

résolu

Pour résoudre le problème précédent, j'ai juste eu à le compiler comme suit:

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias

et utiliser cette API appel en VB6

Public Declare Function add2 Lib "C:\c\dll\mydll" _
    (ByVal num As Integer) As Integer

J'ai appris à ne pas oublier de préciser ByVal ou ByRef explicitement--je viens de retrouver l'adresse de l'argument je suis passé, il semblait, -3048.

7voto

Tom Leys Points 10453

Voici comment faire:

Dans .h

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

extern "C" // Only if you are using C++ rather than C
{    
  EXPORT int __stdcall add2(int num);
  EXPORT int __stdcall mult(int num1, int num2);
}

dans .rpc

extern "C" // Only if you are using C++ rather than C
{    
EXPORT int __stdcall add2(int num)
{
  return num + 2;
}


EXPORT int __stdcall mult(int num1, int num2)
{
  int product;
  product = num1 * num2;
  return product;
}
}

La macro indique à votre module (j'.e votre .fichiers cpp) qu'ils fournissent la dll trucs sur le monde extérieur. Les gens qui comprennent votre .h fichier à importer les mêmes fonctions, de sorte qu'ils vendent à l'EXPORTATION que dire à l'éditeur de liens à l'importation. Vous devez ajouter BUILD_DLL pour le projet d'options de compilation, et vous pouvez le renommer en quelque chose de bien évidemment spécifique à votre projet (dans le cas d'une dll utilise votre dll).

Vous pourriez aussi avoir besoin de créer un .def fichier à renommer les fonctions.aspx) et de dissimuler les noms (C/C++ mangles ces noms). Cette entrée de blog pourrait être intéressant de lancer de point de départ à ce sujet.

Chargement de votre propre personnalisé dll est juste comme système de chargement de la dll. Juste s'assurer que la DLL est sur votre chemin d'accès système. C:\windows\ ou le dossier de travail de votre application sont un endroit facile à mettre votre dll.

6voto

Friedrich Points 4058

Il y a une différence. Vous devez prendre soin de nom ou de modificateur de gagner le C++. Mais sur windows, vous devrez prendre soin de 1) decrating les fonctions exportées à partir de la DLL 2) écrire un soi-disant .def fichier qui répertorie tous les symboles exportés.

Dans Windows lors de la compilation d'une DLL avoir avoir à utiliser

__declspec(dllexport)

mais tout en l'utilisant, vous devez écrire __declspec(dllimport)

Donc, la façon habituelle de faire quelque chose comme

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

Le nom est un peu déroutant, car il est souvent nommé à l'EXPORTATION.. Mais qu'est ce que vous trouverez dans la plupart des en-têtes de somwhere. Si dans votre cas, vous devez écrire (avec la #define)

int DLL_EXPORT ajouter.... int DLL_EXPORT mult...

N'oubliez pas que vous devez ajouter la directive de Préprocesseur BUILD_DLL lors de la construction de la bibliothèque partagée.

Ce qui concerne Friedrich

4voto

dirkgently Points 56879

La chose à surveiller lors de l'écriture de C++ dll est name mangling. Si vous voulez l'interopérabilité entre le C et le C++, vous seriez mieux par l'exportation de non-déformation de style C fonctions de la dll.

Vous avez deux options pour utiliser une dll

  • Soit utiliser un fichier lib pour lier les symboles moment de la compilation, la liaison dynamique
  • Utiliser LoadLibrary() ou certaines fonction appropriée pour charger la bibliothèque, de récupérer un pointeur de fonction (GetProcAddress) et de l'appeler -- exécution de liaison dynamique

L'exportation des classes ne fonctionnera pas si vous suivez la deuxième méthode bien que.

3voto

Arvo Points 4151

Pour VB6:

Vous devez déclarer votre C fonctions __stdcall, sinon vous obtenez le message "invalid convention d'appel" erreurs de type. Sur d'autres de vos questions:

puis-je prendre des arguments par pointeur/référence de la VB front-end?

Oui, utiliser ByRef/ByVal modificateurs.

Peut l'appel de la DLL théorique de la fonction dans le front-end?

Oui, l'utilisation AddressOf déclaration. Vous avez besoin de passer le pointeur de la fonction de dll avant.

Ou prendre un "pointeur de fonction" (je ne sais même pas si c'est possible) à partir de VB et de l'appeler?)

Oui, l'utilisation AddressOf déclaration.

mise à jour (autres questions apparaissent :)):

pour le charger dans VB, dois-je viens de faire la méthode habituelle (ce que je ferais à la charge de winsock.ocx ou une autre exécution, mais de trouver ma DLL) ou dois-je mettre un appel d'API dans un module?

Vous avez besoin de decaler la fonction de l'API en VB6 code suivant:

Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
   (ByVal hwndOwner As Long, _
    ByVal nFolder As Long, _
    ByRef pidl As Long) As Long

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