web-dev-qa-db-fra.com

Une bonne façon de lier des bibliothèques statiques avec dll

Mon projet se construit à travers quelques bibliothèques statiques qui devraient être liées à la bibliothèque de DLL principale et ainsi gagner une seule DLL.

L'utilisation de l'attribut __declspec(dllexport) n'entraîne pas l'apparition de fonctions spécifiées de bibliothèques statiques vers dll, bibliothèques qui ne sont pas du tout liées à dll.

Ensuite, j'ai essayé de créer chaque bibliothèque comme partagée pour obtenir les noms corrects des fonctions exportées et créé un fichier .def basé sur elles. L'utilisation du fichier .def a conduit au résultat.

  1. Doit __declspec(dllexport) et .def-file agir de manière égale dans mon cas?

  2. Est-il possible de générer un fichier .def à partir de sources? Étant donné que j'ai du code C++, je ne suis pas en mesure d'écrire moi-même le fichier .def en raison de la manipulation et des classes de présence dans l'API, l'approche décrite ci-dessus avec les DLL générées temporairement n'est pas cohérente pour la production.

Mettre à jour

Je voudrais expliquer en détail la structure de mon projet. La solution se compose de quelques projets (modules).

+ 
|    
+-+ static_lib1                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ static_lib2                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ dynamic_lib (linked with static_lib1 and static_lib2)
        +                                                
        +--+ src

Chaque sous-projet dépend faiblement des autres, supposons qu'ils ne soient pas connectés pour plus de clarté. Chaque module possède sa propre interface publique. Je veux avoir tous les modules en tant que bibliothèque dynamique unique, donc mon artefact est dynamic_lib.dll, mais en fait les bibliothèques statiques n'y sont pas liées.

14
triclosan

Les bibliothèques statiques ne doivent contenir aucun élément __declspec Ou __attribute((dll...)). Ce ne sont rien de plus que plusieurs fichiers objets (généralement *.obj Ou *.o), Composés en un seul fichier.

Tout ce que vous devez faire pour utiliser une telle bibliothèque (dans .exe Ou .dll) Est d'inclure les en-têtes appropriés et de les lier - avec Visual Studio, c'est assez facile.

Tout d'abord, vous devez savoir 1) où vos bibliothèques statiques sont placées et 2) leurs noms exacts. Accédez aux propriétés du projet, puis General. Target name Contient le nom du fichier de sortie, tandis que Output directory Indique dans quel dossier votre .lib Sera placé.

Remarque: Ce chemin peut être différent pour chaque projet! Pour les solutions multi-projets, je mets toujours cela sur un chemin commun pour éviter les problèmes de configuration.

Maintenant, allez dans les propriétés du projet, qui consommera cette bibliothèque (lien avec elle). Allez dans Linker -> Input puis ajoutez le nom de votre .lib À Additional dependencies (Les entrées sont séparées par un point-virgule):

Linker input

Vous devez ajouter toutes les bibliothèques que vous souhaitez lier. De plus, le dossier dans lequel ces bibliothèques sont placées doit être ajouté à Linker -> General -> Additional library directories. Si tous les .lib Sont placés au même endroit - bon, sinon copiez-les dans un emplacement partagé ou ajoutez plusieurs entrées à la liste Additional library directories.

Et la dernière chose - rappelez-vous, que vous devez également inclure des en-têtes avec des déclarations de fonctions et d'objets, que vous souhaitez utiliser. Chose fondamentale, je sais, mais il faut le mentionner.


MISE À JOUR

externe non résolu lors de la tentative d'utilisation de la bibliothèque de DLL dans un produit externe

Votre problème est pas lié au lien du tout. Le fait est que vous avez mal compris quoi, relier une bibliothèque statique exactement.

Je suppose que les fonctions signalées comme non résolues ne sont pas utilisées par votre DLL, non? Mais vous vous attendez à ce qu'ils soient à l'intérieur, non?

Lorsque votre DLL fait référence à un contenu externe (comme une fonction ou une variable), il est résolu au moment de la liaison - avec toutes les dépendances. Mais c'est tout. Si votre bibliothèque statique a une fonction nommée print_sample_string(), mais que votre DLL ne l'utilise pas, elle ne sera pas attachée à l'image DLL . Réfléchissez bien à cela - pourquoi devrait-il en être ainsi?

Encore plus - les fonctions qui ne sont pas dllexported explicitement ne seront pas visibles de toute façon. Les fonctions ont par défaut un stockage externe - donc, fondamentalement, elles sont du contenu privé de DLL.

Donc, pour répondre directement à votre question - si vous devez utiliser des fonctions/variables de static_lib1.lib, Attachez-le à l'application cliente - tout comme vous l'attachez maintenant à dynamic_lib. Il n'y a pas d'autre moyen. (*)


(*) Vraiment parlant - il y en a. Vous pouvez créer une fonction intermédiaire dans DLL, qui est exportée et appeler la fonction souhaitée à l'intérieur:

Quelque part dans dynamic_lib:

DLL_EXP_IMP long CallFunctionFromA_Lib()
{
     return some_function(); //this function is from static_lib1.lib
}

Quelque part dans .exe:

long result = CallFunctionFromA_Lib(); //internally this will call function from static_lib1.lib

Je ne peux cependant pas imaginer pourquoi voudriez-vous faire cela et ne pas simplement lier A.lib Et l'utiliser directement.

16
Mateusz Grzejek

Ici Raymond Chan explique ce comportement et la meilleure solution est vraiment d'utiliser le fichier def. Quant à la façon de le générer automatiquement pour une bibliothèque statique - this discussion ressemble à un bon point de départ.

4
dewaffled