En ce moment, je fais quelque chose comme ça et cela semble désordonné si je finis à avoir beaucoup de fonctions que je veux faire référence dans ma DLL. Existe-t-il un moyen meilleur et plus propre d'accéder aux fonctions sans avoir à créer un typedef pour chaque définition de fonction afin qu'elle compilait et chargera correctement la fonction. Je veux dire que les définitions de la fonction sont déjà dans le fichier .h et je ne devrais pas avoir à les redéclaré après que je charge la fonction (ou est-ce que je suis?) Y a-t-il une meilleure solution que d'utiliser LoadLibary? Je n'ai pas nécessairement besoin de cette fonction s'il y a une façon de faire la même chose dans les paramètres de projet Visual Studio 2005.
7 Réponses :
Après avoir construit votre fichier .dll obtenir le fichier .lib à proximité et liez votre application de test avec elle. Utilisez des fonctions telles qu'elles sont déclarées dans .h
Il y a une modification mineure que vous devez faire dans votre fichier d'en-tête: p> de cette façon, lorsque vous construisez votre DLL, vous définissez < Code> exports_api code> dans les paramètres de votre projet et les fonctions sont exportés, dans l'application cliente, aucune nécessité de définir quoi que ce soit. p> p>
Super! Est-ce qu'il charge toujours la bibliothèque de manière dynamique que la DLL est conçue pour faire? Cela semble être étrange que vous devez inclure une bibliothèque statique (.Lib) et une dynamique (.dll) afin de le faire?
Oui, il utilise votre DLL, que liber ne contient que des informations nécessaires à la liaison, c'est juste une bibliothèque exportations i>, pas vraiment un «statique lib».
Brian, oui, la bibliothèque est toujours chargée de manière dynamique. La différence est qu'elle est chargée dès que votre application commence, plutôt que d'attendre un appel à chargement du chargement.
L'exportation .Lib est nécessaire pour indiquer à la liaison le nom de la DLL qui doit être chargé. C'est très petit.
Réponse géniale, qui a fonctionné comme un charme et de quoi je cherchais exactement!
Est-ce que cette pratique courante ou est-ce juste un type de chose hacky? Disons que je crée un SDK et distribuerai cette fonctionnalité aux utilisateurs finaux qui sont programmeurs. Seront-ils en mesure d'accéder au code sous-jacent du fichier .lib? Devrons-nous devoir expédier les trois fichiers (.Lib, .dll, et .h)?
Oui c'est une pratique courante, pas un hack. Oui, vous devez livrer les trois fichiers. Et, vous serez peut-être surpris, mais c'est la manière dont la plate-forme MS SDK et la plupart des autres travaux.
Lorsque vous construisez votre DLL, vous devez également obtenir un fichier LIB que vous pouvez créer un lien avec. Cela fera la forte levée en arrière-plan pour vous. Incluez le fichier d'en-tête que vous avez créé, mais changez en dllimport au lieu de Dllexport. Vous pouvez utiliser une définition pour cela, de sorte que, pour votre projet DLL, il utilise dllexport et tous les autres qui n'utilisent pas cette définition utilisera Dllimport. P>
Il vous suffit de faire un chargement manuel de LoadLibrary et de TypeDEF si vous souhaitez charger de manière dynamique la DLL vous-même. Si vous faites l'approche ci-dessus, votre EXE échouera si la DLL n'est pas présente. P>
Vous pouvez également créer le projet DLL dans une bibliothèque statique et charger cela, ce qui sera également débarrassé de ce problème mais augmentera la taille de votre EXE. Ceci n'est bien sûr pas une option si vous voulez vraiment que ce soit une DLL. P>
Importer les bibliothèques (.Lib) simplifie l'utilisation de la DLL dans l'utilisateur code, voir par exemple ici pour un tutoriel de base.
Ils épargnent les utilisateurs du chargement de la DLL, à l'aide de getProcAddress () code> et fonctionnent eux-mêmes - ils se trouvent statiquement à la bibliothèque d'importation plutôt que le travail pour eux. P>
Vous pouvez créer un lien vers les symboles de la DLL directement au lieu d'utiliser exemple de fichier d'en-tête SNIPPET: P> getProcAdress () code>, qui obtient l'adresse d'une fonction au moment de l'exécution. #if defined(MY_LIB_STATIC)
#define MY_LIB_EXPORT
#elif defined(MY_LIB_EXPORTS)
#define MY_LIB_EXPORT __declspec(dllexport)
#else
#define MY_LIB_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
int MY_LIB_EXPORT Factorial(int n);
#ifdef __cplusplus
}
#endif
Vous ne pouvez pas lier 'directement' à un symbole DLLS - sa chargée de manière dynamique.
Je suis conscient de la façon dont la liaison dynamique fonctionne. Néanmoins, je considère qu'il est plus "direct" de relier de manière à résoudre le temps de chargement par la liaison dynamique que de le résoudre après le démarrage principal (). Ce contraste est ce que je voulais faire attention à en disant "direct".
Dans le monde Windows, il y a (au moins) 4 façons d'utiliser des DLL: p>
Je n'ai pas à expliquer Dynamique d'exécution LIENNEZ EM> Puisque vous le faites déjà. Je choisis de ne pas expliquer la liaison dynamique de délai de chargement de retard em> au-delà de décrire simplement ce qu'il est en termes généraux. La charge de retard est essentiellement identique à la liaison dynamique de charge de charge, sauf qu'il est fait juste dans le temps au lieu de la charge de l'application. Ce n'est pas aussi utile ni aussi bénéfique que vous pourriez penser, il est difficile de travailler avec et de manière difficile à coder. Alors n'allons pas là, au moins pour le moment. le transfert de DLL em> est encore plus exotique que le chargement de retard - si exotique, je n'en ai même jamais entendu parler jusqu'à @MOX l'a mentionné dans les commentaires. Je vous laisserai lire le lien ci-dessus pour en apprendre, mais il suffit de dire que le transfert de la DLL est lorsque vous appelez une fonction exportée dans une DLL, mais cette demande est en réalité transmise em> à une autre fonction dans un DLL différente. p>
C'est ce que je considérerais comme la Vanilla DLL relie em>. p>
C'est ce que la plupart des gens se réfèrent lorsqu'ils se réfèrent à l'utilisation de DLL dans leurs applications. Vous venez de 1) Vous obtenez généralement 3 fichiers: une DLL avec le code d'exécution, un fichier LIB et un fichier d'en-tête. Le fichier d'en-tête est juste un fichier d'en-tête - il décrit toutes les installations de la DLL que vous pouvez utiliser. P>
2) Vous écrivez votre application, 3) Vous allez sur les paramètres de la liaison pour votre projet et ajoutez une "dépendance supplémentaire de la bibliothèque", spécifiant le fichier LIB. Le fichier LIB indique à la liaison où les fonctions et les objets que vous utilisez à partir du fichier h résident dans la mémoire (en termes relatifs, non absolus, évidemment). P>
4) Compilez votre application. Si vous avez tout configuré correctement, cela devrait compiler, relier et exécuter. Lorsque vous obtenez des erreurs de liaison "non résolues de référence externe", cela est généralement dû à des choses qui ne sont pas configurées correctement. Vous ne pouvez pas non plus spécifier le chemin correct vers le fichier LIB ou vous devez inclure plus de fichiers lib. P> Liaison dynamique de chargement de temps h3>
#include code> le fichier d'en-tête de la DLL et lien vers le fichier LIB. Pas besoin de getProcAddress () code> ou créer un pointeur de fonction Typefs. Voici comment cela fonctionne en un mot: p>
#include code> 'ing dans le fichier d'en-tête de la DLL et effectuez des appels sur ces fonctions, comme vous pouvez utiliser n'importe quelle fonction dans n'importe quel fichier d'en-tête. Le compilateur connaît les noms des fonctions et des objets que vous utilisez car ils sont dans le fichier d'en-tête de la DLL. Mais cela ne sait pas où ils sont encore en mémoire. C'est là que le fichier lib est ... p>
@John, bonne réponse, mais votre terminologie semble être en arrière selon le lien que vous avez inclus. MSDN définit «la liaison dynamique de l'exécution» pour être ce que l'OP est en train de faire et de «lier dynamique de chargement» pour être ce que vous décrivez.
Une quart de DLL d'utilisation est la suivante: lien dynamique transféré ( blogs.msdn.com/b/oldnewthing/archive/2008/02/04/7439592.asp x )
@MOX: Merci, j'avais jamais entendu parler de ça avant! Édité.
@John: pas de problème! Un joli effet secondaire de si. :-)
Pourquoi n'atteignez-vous pas VS pour générer une bibliothèque statique de shim autour de votre DLL. De cette façon, tout ce que vous avez à faire est d'ajouter une convention appelante dans le fichier d'en-tête et d'ajouter quelques directives pré-procaissatrice. Le moyen le plus simple de déterminer comment faire est de créer un nouveau projet DLL (Visual C ++> Win32, choisissez Projet DLL, vérifiez les symboles d'importation)
Utilisez le fichier d'en-tête principal à titre d'exemple sur la manière de décorer vos classes avec la convention d'appel d'importation / exportation. Cette tête est le plus important car il explique comment utiliser les fonctions et les classes déclaré là-bas: p> puis, dans le projet qui utilise cette DLL inclut simplement le fichier d'en-tête et < code> .lib code> que le projet DLL généré. De cette façon, il charge automatiquement la DLL et vous pouvez utiliser toutes les fonctions comme si elles sont liées statiquement. P> p>
Un outil d'interface graphique n'est pas substitué à savoir quel est le problème. J'encourageais la lecture et la compréhension des fichiers d'en-tête que cet assistant produit pour vous.
Bien sûr, vous ne pas besoin em> la em> le typef ou, exploitant l'initialisation de C ++ initialise et testez idiom p> étant donné cela pour ranger la répétition du type p> mais pas à l'aide d'un TYPEDEF est généralement plus pire plutôt que mieux, les types de pointeur de la fonction de C étant un peu délicat pour Obtenez de la bonne sauf si vous les utilisez régulièrement. (Si vous les utilisez régulièrement, votre logiciel peut être un peu orthodoxe). P> Le Microsoft DLLIMPORT CODE> Extensions et compilateur Créez une bibliothèque statique qui fait le chargement pour vous et fournit des trampolines ou des thunks, car d'autres ont affiché. Sauf si vous créez un système de plug-in qui ne sait pas quelle DLL il chargera, utilisez-le à la place. P> P>
Vous n'avez pas eu le point. Tout cela était de ne pas avoir à déclarer (à nouveau) la définition de fonction déjà dans le fichier d'en-tête. Que ce soit avec un typedef ou non, il est laid de devoir refroidir comment la signature de la fonction semble.
J'ai eu le point, mais la question n'a pas été spécifiée si elle sélectionnait de manière dynamique la DLL ou qu'elle était connue à l'heure de la compilation. Pour le premier, vous ne pouvez pas utiliser dllimport.
Je ne vois pas une vraie question ici. Que voulez-vous vous débarrasser de TapeDEF?
Il n'y a qu'un seul typdef j'ai mis dans mon code et c'est: "Typeft Int (* FactorialPtr) (int);"
Brian, juste comme une note latérale, votre test de l'unité n'a pas besoin de tester la charge de la bibliothèque dans Windows. Au lieu d'utiliser votre DLL dans des tests, vous pouvez ajouter un autre projet à votre solution qui utiliserait les mêmes fichiers source + vos sources de test et produisez un exécutable Testrunner. Ce que vous avez en ce moment ressemble plus à un test d'intégration plutôt qu'un test unitaire.
Je vois ce que tu veux dire, mais je joue comme l'utilisateur final d'un SDK. Les développeurs créeront le SDK et je recevrai le code comme si j'étais quelqu'un qui allait utiliser le SDK. Ensuite, je vais faire "test unitaire". Bien que j'ai accès aux fonctions directement dans les projets du développeur, je ne veux pas toucher leur code. Merci de m'avoir mis au courant.