La principale différence est que vous incluez des bibliothèques liées statiques avec votre application. Ils sont liés lorsque vous créez votre application. Les bibliothèques dynamiques sont liées au moment de l'exécution, vous n'avez donc pas besoin de les inclure dans votre application. De nos jours, les bibliothèques dynamiques sont utilisées pour réduire la taille des applications en disposant de nombreuses bibliothèques dynamiques sur l'ordinateur de chacun.
Les bibliothèques dynamiques permettent également aux utilisateurs de mettre à jour les bibliothèques sans reconstruire les applications clientes. Si un bogue est trouvé dans une bibliothèque que vous utilisez dans votre application et qu'elle est liée de manière statique, vous devrez reconstruire votre application et la rediffuser à tous vos utilisateurs. Si un bogue est détecté dans une bibliothèque liée dynamiquement, tous vos utilisateurs n'ont qu'à mettre à jour leurs bibliothèques et votre application n'a pas besoin de mise à jour.
Lorsqu'un programme C++ est compilé. Il doit avoir des références aux fonctions et au code de la bibliothèque C++ (par exemple, le code de la bibliothèque).
Supposons que nous ayons une hypothétique bibliothèque partagée appelée libdyno.so
. Vous pourrez éventuellement jeter un coup d'œil à l'intérieur en utilisant objdump
ou nm
.
objdump --syms libdyno.so
Vous pouvez le faire aujourd'hui sur votre système avec n'importe quelle bibliothèque partagée. objdump
sur un MAC s'appelle gobjdump
et est livré avec infusion dans le binutils
forfait. Essayez ceci sur un mac...
gobjdump --syms /usr/lib/libz.dylib
Vous pouvez maintenant voir que les symboles sont contenus dans l'objet partagé. Lorsque vous link
avec l'objet partagé, vous utilisez généralement quelque chose comme
g++ -Wall -g -pedantic -ldyno DynoLib_main.cpp -o dyno_main
Notez le -ldyno
dans cette commande. Cela indique au compilateur (vraiment l'éditeur de liens ld) de rechercher un fichier objet partagé appelé libdyno.so
partout où il les cherche normalement. Une fois qu'il trouve cet objet, il peut alors trouver les symboles dont il a besoin. Il n'y a pas de dépendance circulaire car vous, le développeur, avez demandé le chargement de la bibliothèque dynamique en spécifiant le -l
drapeau.
Comment et quand utiliseriez-vous une bibliothèque dynamique ? Comment en faire un ? Comme dans quelle est la commande de compilation spécifique qui est utilisée pour produire un tel fichier à partir d'un fichier .cpp standard
Créez un fichier appelé DynoLib.cpp
#include "DynoLib.h"
DynamicLib::DynamicLib() {}
int DynamicLib::square(int a) {
return a * a;
}
Créez un fichier appelé DynoLib.h
#ifndef DYNOLIB_H
#define DYNOLIB_H
class DynamicLib {
public:
DynamicLib();
int square(int a);
};
#endif
Compilez-les pour en faire une bibliothèque partagée comme suit. Ceci est spécifique à Linux...
g++ -Wall -g -pedantic -shared -std=c++11 DynoLib.cpp -o libdyno.so
Vous pouvez maintenant inspecter cet objet en utilisant la commande que j'ai donnée plus tôt, c'est-à-dire
objdump --syms libdyno.so
Créez maintenant un fichier appelé DynoLib_main.cpp qui sera lié à libdyno.so
et utilisez la fonction que nous venons de définir.
#include "DynoLib.h"
#include <iostream>
using namespace std;
int main(void) {
DynamicLib *lib = new DynamicLib();
std::cout << "Square " << lib->square(1729) << std::endl;
return 1;
}
Compilez-le comme suit
g++ -Wall -g -pedantic -L. -ldyno DynoLib_main.cpp -o dyno_main
./dyno_main
Square 2989441
Vous pouvez également jeter un œil au binaire principal en utilisant nm
. Dans ce qui suit, je vois s'il y a quelque chose avec la chaîne square
c'est-à-dire le symbole dont j'ai besoin de libdyno.so
de quelque manière que ce soit référencé dans mon binaire.
nm dyno_runner |grep square
U _ZN10DynamicLib6squareEi
La réponse est oui. Le U
majuscule signifie indéfini, mais il s'agit du nom de symbole de notre méthode carrée dans la classe DynamicLib que nous avons créée précédemment. Le nom étrange est dû à la modification du nom, qui est son propre sujet.
Comment puis-je savoir lesquels lier statiquement comme je le ferais avec un fichier regular.o et lesquels sont censés être liés dynamiquement ?
Vous n'avez pas besoin de savoir. Vous spécifiez ce que vous voulez lier et laissez le compilateur (et l'éditeur de liens, etc.) faire le travail. Notez le -l
flag nomme la bibliothèque et le -L
lui indique où chercher. Il y a une écriture décente sur la façon dont le compilateur trouve quelque chose ici
gcc Linkage option -L :autres manières de spécifier le chemin d'accès à la bibliothèque dynamique
Ou jetez un oeil à man ld
.
A quoi servent les drapeaux -L et -l ? Que signifie spécifier par exemple un indicateur -lusb sur la ligne de commande ?
Voir le lien ci-dessus. Cela vient de man ld
..
-L répertoirerecherche
Ajoutez le chemin searchdir à la liste des chemins que ld recherchera pour les bibliothèques d'archives et les scripts de contrôle ld. Vous pouvez utiliser cette option autant de fois que vous le souhaitez. Les répertoires sont recherchés dans l'ordre dans lequel ils sont spécifiés sur la ligne de commande. Les répertoires spécifiés sur la ligne de commande sont recherchés avant les répertoires par défaut. Toutes les options -L s'appliquent à toutes les options -l, quel que soit l'ordre dans lequel elles apparaissent. Les options -L n'affectent pas la façon dont ld recherche un script de lien à moins que l'option -T ne soit spécifiée.`
Si vous avez réussi à arriver ici, il est avantageux d'en savoir plus sur l'éditeur de liens, c'est-à-dire ld. Il joue un rôle important et est la source d'une tonne de confusion car la plupart des gens commencent par traiter avec un compilateur et pensent que compiler == linker
et ce n'est pas vrai.