Existe-t-il un meilleur moyen de charger une DLL en C ++?
Maintenant je ne quelque chose comme cela et il semble désordonné, si je finis à avoir beaucoup de fonctions que je veux la référence dans ma DLL. Est-il mieux et plus propre façon d'accéder à des fonctions sans avoir à créer un typedef pour chaque définition de la fonction, de sorte qu'il sera de compiler et charger la fonction correctement. Je veux dire les définitions de fonctions sont déjà dans le .h de fichier et je ne devrais pas avoir à redeclare après je charge la fonction (ou dois-je?) Est-il une meilleure solution que d'utiliser LoadLibary? Je n'ai pas forcément besoin de cette fonction si il ya une manière que je peux faire la même chose au sein de Visual Studio 2005 paramètres du projet.
BHannan_Test_Class.h
#include "stdafx.h"
#include <windows.h>
#ifndef BHANNAN_TEST_CLASS_H_
#define BHANNAN_TEST_CLASS_H_
extern "C" {
//Returns n! (the factorial of n). For negative n, n! is defined to be 1.
int __declspec (dllexport) Factorial(int n);
//Returns true iff n is a prime number.
bool __declspec (dllexport) IsPrime(int n);
}
#endif //BHANNAN_TEST_CLASS_H_
BHannan_Test_Class.cpp
#include "stdafx.h"
#include "BHannan_Test_Class.h"
//Returns n! (the factorial of n). For negative n, n! is defined to be 1.
int Factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
//Returns true iff n is a prime number.
bool IsPrime(int n) {
//Trivial case 1: small numbers
if (n <= 1) return false;
//Trivial case 2: even numbers
if (n % 2 == 0) return n == 2;
//Now, we have that n is odd and n >= 3.
//Try to divide n by every odd number i, starting from 3
for (int i = 3; ; i += 2) {
//We only have to try i up to the squre root of n
if (i > n/i) break;
//Now, we have i <= n/i < n.
//If n is divisible by i, n is not prime.
if (n % i == 0) return false;
}
//n has no integer factor in the range (1, n), and thus is prime.
return true;
}
dll_test.cpp
#include <BHannan_Test_Class.h>
typedef int (*FactorialPtr) (int);
FactorialPtr myFactorial=NULL;
//Tests factorial of negative numbers.
TEST(FactorialTest, Negative) {
HMODULE myDLL = LoadLibrary("BHannan_Sample_DLL.dll");
if(myDLL) {
myFactorial = (FactorialPtr) GetProcAddress(myDLL,"Factorial");
if(myFactorial)
{
EXPECT_EQ(1, myFactorial(-5));
EXPECT_EQ(1, myFactorial(-1));
EXPECT_TRUE(myFactorial(-10) > 0);
}
FreeLibrary(myDLL);
}
}
source d'informationauteur Brian T Hannan
Vous devez vous connecter pour publier un commentaire.
Après la construction de votre .dll obtenir le .fichier lib proximité et le lien de votre application de test. Utiliser des fonctions comme ils sont déclarés dans .h
Il y a un changement mineur que vous devez faire dans votre fichier d'en-tête:
De cette façon, lors de la construction de votre fichier dll, vous définissez
EXPORTS_API
dans les paramètres de votre projet et les fonctions exportés, dans l'application cliente, pas besoin de définir quoi que ce soit.Dans le monde Windows, il y a (au moins) 4 façons d'utiliser Dll:
Je n'ai pas à expliquer Moment de l'Exécution de la Liaison Dynamique puisque vous êtes déjà à le faire. Je choisis de ne pas expliquer de Chargement de Délai Liaison Dynamique maintenant au-delà de simplement décrire ce que c'est en termes généraux. Le retard de la Charge est essentiellement la même que les Temps de Charge Dynamique Reliant sauf que c'est fait Juste-À-Temps au lieu d'au chargement de l'application. Ce n'est pas comme utiles ou bénéfiques que vous pourriez le penser, il est difficile de travailler avec et difficile à code pour. Afin de ne pas laisser y aller, au moins pour l'instant. DLL Transfert est encore plus exotique que de Retarder le Chargement -- exotique, je n'avais même jamais entendu parler de lui jusqu'à ce que @mox mentionné dans les commentaires. Je vous laisse lire le lien ci-dessus pour apprendre à ce sujet, mais il suffit de dire que DLL de Transfert est lorsque vous appelez une fonction exportée dans une DLL, mais qui demande en fait transmis à une autre fonction dans une DLL différent.
De Charge-Temps De La Liaison Dynamique
C'est ce que je considère être Vanille de Liaison des DLL.
C'est ce que la plupart des gens se réfèrent à quand ils se réfèrent à l'aide de Dll dans leurs applications. Vous venez de
#include
la DLL fichier d'en-tête et un lien vers le fichier LIB. Pas besoin deGetProcAddress()
ou créer pointeur de fonction typedefs. Voici comment cela fonctionne en un mot:1) Vous obtenez généralement 3 fichiers: un DLL avec le moteur d'exécution de code, un fichier LIB et un fichier d'en-tête. L'en-tête de fichier est juste un fichier d'en-tête -- il décrit toutes les facilités dans la DLL que vous pouvez utiliser.
2) Vous écrivez votre application,
#include
'ing le fichier d'en-tête à partir de la DLL et de faire des appels à ces fonctions, comme vous le feriez utiliser n'importe quelle fonction dans tout fichier d'en-tête. Le compilateur connaît les noms de fonctions et d'objets que vous utilisez, car ils sont dans le DLL fichier d'en-tête. Mais il ne sait pas où ils sont dans la mémoire encore. C'est là le fichier LIB est dans...3) Vous accédez à l'éditeur de liens paramètres de votre projet et d'ajouter un "supplémentaires de la bibliothèque de dépendance", en spécifiant le fichier LIB. Le fichier LIB indique à l'éditeur de liens où les fonctions et les objets que vous utilisez depuis la H de fichiers résident dans la mémoire (en terme relatif, pas absolu, évidemment).
4) Compiler votre application. Si vous avez mis tout en place correctement, il devrait compiler, de lien et de l'exécuter. Lorsque vous obtenez "externe non résolu de référence" de l'éditeur de liens erreurs souvent, cela est dû à des choses de ne pas être mis en place. Vous pouvez vous n'avez pas spécifié le chemin d'accès correct au fichier LIB ou vous avez besoin d'inclure plus de fichiers LIB.
Bibliothèques d'importation (.lib) simplifier l'utilisation de la DLL dans le code de l'utilisateur, voir, par exemple, ici pour un tutoriel de base.
Elles épargnent les utilisateurs de chargement de la DLL, à l'aide de
GetProcAddress()
et des pointeurs de fonction eux-mêmes - ils lier statiquement à la bibliothèque d'importation au lieu qui fait le travail pour eux.Pourquoi ne pas vous obtenez VS pour générer un calage statique de la bibliothèque autour de votre DLL. De cette façon, tout ce que vous avez à faire est d'ajouter une convention d'appel dans le fichier d'en-tête et ajouter un couple de pré-procesor directives. La façon la plus simple de comprendre la façon de le faire est de créer un nouveau projet DLL (Visual C++>Win32 Projet, Choisissez DLL Projet, cochez la case Importer les symboles)
le texte d'alt http://img341.imageshack.us/img341/7048/dll.png
Utiliser l'en-tête de fichier comme un exemple sur la façon de décorer vos classes à l'importation et à l'exportation convention d'appel. Cette tête est important car il explique comment utiliser les fonctions et les classes déclarées:
Puis, dans le projet qui utilise cette DLL il suffit d'inclure le fichier d'en-tête et
.lib
que le projet de DLL générée. De cette façon, il se charge automatiquement de la DLL et vous pouvez utiliser toutes les fonctions comme si statiquement.Lorsque vous générez votre fichier dll, vous devez également obtenir un fichier lib que vous pouvez lier avec. Que va faire le gros du travail en arrière-plan pour vous. Inclure le fichier d'en-tête que vous avez créé, mais le changement dans dllimport au lieu de dllexport. Vous pouvez utiliser une définition pour que, afin que, pour votre projet de dll, il utilise dllexport et tous les autres qui n'utilisent pas cet définir utilisera dllimport.
Vous avez seulement besoin de faire un manuel LoadLibrary et le typedef si vous voulez charger dynamiquement la dll vous-même. Si vous ne l'approche ci-dessus votre exe échouera si la dll n'est pas présent.
Vous pouvez également créer la dll projet dans une bibliothèque statique et de la charge qu'à la place, ce qui permettra également de se débarrasser de ce problème, mais d'augmenter la taille de votre fichier exe. Bien sûr ce n'est pas une option si vous voulez vraiment être un dll.
Vous pouvez faire un lien vers la DLL symboles directement au lieu d'utiliser
GetProcAddress()
qui obtient l'adresse d'une fonction lors de l'exécution.Exemple de fichier d'en-tête de fragment:
Puis dans
BHannan_Test_Class.cpp
vous#define MY_LIB_EXPORTS
avant, y compris l'en-tête.Dans
dll_test.cpp
vous devez inclure l'en-tête et il suffit d'utiliserFactorial()
que vous utilisez la fonction normale. Lors de la liaison, vous souhaitez lier à la bibliothèque d'importation que la construction de votre fichier DLL produit. Cela rend les symboles à partir de la DLL à la disposition du code qui est lié à elle.Bien sûr, vous n'avez pas besoin le typedef
ou, en exploitant le C++ permet d'initialiser et tester idiome
compte tenu de ce à nettoyer la répétition du type
Mais de ne pas utiliser un typedef est généralement pire plutôt que le contraire, comme C est le pointeur de la fonction des types de sont un peu difficile à obtenir, sauf si vous utilisez régulièrement. (si vous les utilisez régulièrement, c'est que votre logiciel peut être peu orthodoxe).
Microsoft
dllimport
extensions et compilateur de créer une bibliothèque statique qui ne le chargement pour vous et fournit des trampolines ou les thunks, comme d'autres l'ont publié. Sauf si vous êtes en train de créer un système de plug-in qui ne sait pas qui dll il charge, puis de l'utiliser à la place.