Le but de ce partage estLe butde permettre à chacun d'apprendre comment créer et utiliser des bibliothèques statiques et dynamiques, de comprendre les différences entre bibliothèques statiques et dynamiques, et de savoir comment choisir lors de leur utilisation. Nous n'entrerons pas dans les détails des formats sous-jacents et des dispositions mémoire des bibliothèques statiques et dynamiques. Pour les personnes intéressées, nous recommandons un livre : « Self-Cultivation of Programmers - Linking, Loading, and Libraries ».

1. Qu'est-ce qu'une bibliothèque

Une bibliothèque est du code écrit, existant et mature qui peut être réutilisé.En réalité, chaque programme dépend de nombreuses bibliothèques sous-jacentes de base. Il est impossible que tout le monde écrive du code à partir de zéro. Par conséquent, l'existence des bibliothèques revêt une importance extraordinaire.。

Essentiellement, une bibliothèque est une forme binaire de code exécutable qui peut être chargée en mémoire par le système d'exploitation et exécutée. Il existe deux types de bibliothèques : les bibliothèques statiques (.a, .lib) et les bibliothèques dynamiques (.so, .dll).

Ce que l'on appelle statique et dynamique fait référence à l'édition de liens. Passons en revue les étapes pour compiler un programme en un exécutable :

clip_image002[4]

Figure : processus de compilation

2. Bibliothèques statiques

On l'appelle « bibliothèque statique » parce que, lors de l'étape de liaison, les fichiers objet .o générés par l'assemblage sont liés et empaquetés avec les bibliothèques référencées dans le fichier exécutable. Par conséquent, la méthode de liaison correspondante est appelée liaison statique.

Réfléchissez : une bibliothèque statique est liée avec les fichiers objet générés par l'assemblage dans un exécutable, donc la bibliothèque statique doit être de format similaire aux fichiers .o. En fait, une bibliothèque statique peut simplement être considérée commeun groupe de fichiers objet (.o/.objune collection de fichiers)C'est-à-dire un fichier formé en compressant et empaquetant de nombreux fichiers objet. Résumé des caractéristiques d'une bibliothèque statique :

- La liaison d'une bibliothèque statique aux bibliothèques de fonctions est effectuée au moment de la compilation.

- À l'exécution, le programme n'a rien à voir avec la bibliothèque de fonctions, ce qui facilite le portage.

- Gaspille de l'espace et des ressources, car tous les fichiers objet associés et les bibliothèques de fonctions impliquées sont liés ensemble dans un seul fichier exécutable.

Ci-dessous, nous écrivons quelques classes C++ simples pour des opérations arithmétiques de base, les compilons dans une bibliothèque statique que d'autres pourront utiliser. Le fichier d'en-tête est le suivant :

Fichier d'en-tête StaticMath.h
#pragma once
class StaticMath
{
public:
    StaticMath(void);
    ~StaticMath(void);
 
    static double add(double a, double b);//加法
    static double sub(double a, double b);//减法
    static double mul(double a, double b);//乘法
    static double div(double a, double b);//除法

    void print();
};

Sous Linux, utilisezaroutils, et sous Windows utilisez VSlib.exepour compresser les fichiers objet ensemble, et les numéroter et les indexer pour faciliter la recherche et la récupération. Les étapes générales de création d'une bibliothèque statique sont illustrées dans la figure :

clip_image004[4]

Figure : Processus de création d'une bibliothèque statique

2.1. Création et utilisation de bibliothèques statiques sous Linux

2.1.1. Règles de nommage des bibliothèques statiques sous Linux

La convention de nommage des bibliothèques statiques Linux doit être "lib[your_library_name].a" : lib est le préfixe, le milieu est le nom de la bibliothèque statique, et l'extension est .a.

2.1.2. Création d'une bibliothèque statique (.a)

D'après le processus ci-dessus, nous pouvons savoir que le processus de création d'une bibliothèque statique sous Linux est le suivant :

- Tout d'abord, compilez le fichier de code en fichier objet .o (StaticMath.o)

g++ -c StaticMath.cpp

Remarque : utilisez le paramètre -c ; sinon, il sera compilé directement en fichier exécutable.

- Ensuite, utilisez l'outil ar pour empaqueter le fichier objet dans un fichier de bibliothèque statique .a

ar -crv libstaticmath.a StaticMath.o

Générez la bibliothèque statiquelibstaticmath.a。

clip_image006[4]

Pour les projets plus volumineux, des fichiers makefile (et des outils de gestion de projet tels que CMake) sont écrits pour générer des bibliothèques statiques ; saisir plusieurs commandes est trop fastidieux.

2.1.3. Utilisation des bibliothèques statiques

Écrivez du code de test qui utilise la bibliothèque statique créée ci-dessus :

Code de test :
#include "StaticMath.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << StaticMath::add(a, b) << endl;
    cout << "a - b = " << StaticMath::sub(a, b) << endl;
    cout << "a * b = " << StaticMath::mul(a, b) << endl;
    cout << "a / b = " << StaticMath::div(a, b) << endl;

    StaticMath sm;
    sm.print();

    system("pause");
    return 0;
}

Pour utiliser une bibliothèque statique sous Linux, il vous suffit de spécifier le chemin de recherche de la bibliothèque statique (option -L) et de spécifier le nom de la bibliothèque statique (aucun préfixe lib ni suffixe .a nécessaire, option -l) au moment de la compilation.

# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath

clip_image008[4]

- -L : indique le répertoire où se trouve la bibliothèque à lier

- -l : spécifie la bibliothèque dynamique nécessaire à l'édition de liens. Le compilateur applique une règle de nommage implicite lorsqu'il recherche des bibliothèques dynamiques : il ajoute lib devant le nom donné et .a ou .so après celui-ci pour déterminer le nom de la bibliothèque.

2.2. Création et utilisation de bibliothèques statiques sous Windows

2.2.1. Création d'une bibliothèque statique (.lib)

Si vous utilisez la ligne de commande VS pour générer une bibliothèque statique, le programme est également généré en deux étapes :

- Tout d'abord, en utilisant l'option de compilation/cdeCl.execompilez le code (cl /c StaticMath.cpp), créez un fichier objet nommé "StaticMath.obj".

- Ensuite, utilisez le gestionnaire de bibliothèquesLib.exepour lier le code (lib StaticMath.obj), créez la bibliothèque statique StaticMath.lib.

Bien sûr, nous ne procédons généralement pas ainsi ; il est plus pratique d'utiliser les paramètres de projet VS. Lors de la création d'une application console Win32, cochez le type Bibliothèque statique ; ouvrez les "Pages de propriétés" du projet -> "Propriétés de configuration" -> "Général", et sélectionnez Bibliothèque statique comme Type de configuration.

clip_image010[4]

Figure : paramètres des propriétés du projet de bibliothèque statique VS

Générez le projet pour créer la bibliothèque statique.

2.2.2. Utilisation de bibliothèques statiques

Le code de test est le même que sous Linux. Il existe 3 façons de l'utiliser :

Méthode 1 :

Comment utiliser une bibliothèque statique dans VS :

- Dans le projet "Pages de propriétés" -> "Propriétés communes" -> "Framework et références" -> "Ajouter une référence", la boîte de dialogue "Ajouter une référence" apparaîtra. L'onglet "Projet" répertorie les projets de la solution actuelle et toutes les bibliothèques qui peuvent être référencées. Dans l'onglet "Projet", sélectionnez StaticLibrary. Cliquez sur "OK".

clip_image012[4]

- Ajoutez le répertoire du fichier d'en-tête StaticMath.h ; vous devez modifier le chemin du répertoire include. Ouvrez le projet "Pages de propriétés" -> "Propriétés de configuration" -> "C/C++" -> "Général", et dans la valeur de la propriété "Répertoires Include supplémentaires", saisissez le chemin du répertoire contenant le fichier d'en-tête StaticMath.h ou accédez à ce répertoire.

clip_image014[4]

Compilation et exécution OK.

clip_image015[4]

Figure : résultat du test de la bibliothèque statique (VS)

Si la bibliothèque statique référencée n'est pas un sous-projet de la même solution, mais utilise une bibliothèque statique tierce lib et un fichier d'en-tête, la méthode ci-dessus ne peut pas être utilisée. Il existe 2 autres méthodes qui sont également réalisables.

Méthode 2 :

Ouvrez les "Pages de propriétés" du projet -> "Propriétés de configuration" -> "Éditeur de liens" -> "Ligne de commande", et entrez le chemin complet de la bibliothèque statique.

clip_image017[4]

Méthode 3 :

- "Pages de propriétés" -> "Propriétés de configuration" -> "Éditeur de liens" -> "Général", entrez le répertoire où se trouve la bibliothèque statique dans Répertoires de bibliothèques supplémentaires ;

- "Pages de propriétés" -> "Propriétés de configuration" -> "Éditeur de liens" -> "Entrée", entrez le nom de la bibliothèque statique StaticLibrary.lib dans Dépendances supplémentaires.

clip_image019[4]

3. Bibliothèques dynamiques

D'après l'introduction ci-dessus, les bibliothèques statiques sont faciles à utiliser et à comprendre, et atteignent également l'objectif de réutilisation du code. Alors pourquoi avons-nous encore besoin de bibliothèques dynamiques ?

3.1. Pourquoi les bibliothèques dynamiques sont-elles encore nécessaires ?

Le besoin de bibliothèques dynamiques est en fait causé par les caractéristiques des bibliothèques statiques.

- Le gaspillage d'espace est un problème des bibliothèques statiques.

clip_image021[4]

- Un autre problème est que les bibliothèques statiques compliquent les mises à jour, le déploiement et la publication des programmes. Si la bibliothèque statique liba.lib est mise à jour, toutes les applications qui l'utilisent doivent être recompilées et publiées auprès des utilisateurs (pour les utilisateurs, il peut s'agir d'un très petit changement, mais cela entraîne le retéléchargement de tout le programme,mise à jour complète)。

Les bibliothèques dynamiques ne sont pas intégrées au code objet au moment de la compilation, mais sont chargées uniquement lorsque le programme s'exécute.Si différentes applications font appel à la même bibliothèque, alors une seule instance de cette bibliothèque partagée est nécessaire en mémoire., évitant ainsi le problème de gaspillage d'espace. Les bibliothèques dynamiques ne sont chargées que lorsque le programme s'exécute, ce qui résout aussi les problèmes que les bibliothèques statiques posent pour les mises à jour, le déploiement et la publication des programmes. Les utilisateurs n'ont qu'à mettre à jour la bibliothèque dynamique,mise à jour incrémentielle.。

clip_image023[4]

Résumé des caractéristiques des bibliothèques dynamiques :

- Les bibliothèques dynamiques reportent l'édition de liens et le chargement de certaines fonctions de bibliothèque au moment de l'exécution du programme.

- Elles permettent de réaliser le partage de ressources entre processus. (C'est pourquoi les bibliothèques dynamiques sont aussi appelées bibliothèques partagées.)

- Elles simplifient la mise à niveau de certains programmes.

- Elles peuvent même véritablement parvenir à ce que l'édition de liens et le chargement soient complètement contrôlés par le programmeur dans le code du programme (appel explicite)。

Windows et Linux ont des formats de fichiers exécutables différents, il y a donc quelques différences lors de la création de bibliothèques dynamiques.

Sous le système Windows, le format de fichier exécutable est le format PE, et une bibliothèque dynamique nécessite unefonction DllMain qui sert de point d'entrée d'initialisation. Généralement, lors de la déclaration de fonctions exportées, vous devez utiliser _declspec(dllexport).keyword。

- Sous Linux, les fichiers exécutables compilés par gcc sont au format ELF par défaut.Aucun point d'entrée d'initialisation n'est requis, et les fonctions n'ont pas besoin de déclarations spéciales.Cela rend le développement plus pratique.

Contrairement à la création d'une bibliothèque statique, aucun outil d'empaquetage (ar, lib.exe) n'est nécessaire ; vous pouvez créer une bibliothèque dynamique directement avec le compilateur.

3.2. Création et utilisation de bibliothèques dynamiques sous Linux

3.2.1. Conventions de nommage des bibliothèques dynamiques Linux

Le nom d'une bibliothèque de liens dynamiques prend la forme libxxx.so, avec le préfixe "lib" et le suffixe ".so".

- Pour le fichier de bibliothèque réel, chaque bibliothèque partagée a un nom spécial appelé "soname". Après le démarrage du programme, il utilise ce nom pour indiquer au chargeur dynamique quelle bibliothèque partagée charger.

- Dans le système de fichiers, soname n'est qu'un lien vers la bibliothèque dynamique réelle. Pour les bibliothèques dynamiques, chaque bibliothèque possède également un autre nom que le compilateur peut utiliser. Il s'agit d'un fichier de lien pointant vers le fichier image réel de la bibliothèque (lib+soname+.so).

3.2.2. Création d'une bibliothèque dynamique (.so)

Écrivez le code de la bibliothèque dynamique pour les opérations arithmétiques :

Fichier d'en-tête DynamicMath.h
#pragma once
class DynamicMath
{
public:
        DynamicMath(void);
        ~DynamicMath(void); 

        static double add(double a, double b);//加法
        static double sub(double a, double b);//减法
        static double mul(double a, double b);//乘法
        static double div(double a, double b);//除法
        void print();
};

- D'abord, générez le fichier objet ; à ce stade, ajoutez l'option du compilateur -fpic.

g++ -fPIC -c DynamicMath.cpp

-fPIC crée du code indépendant de la position (PIC), afin qu'il puisse être partagé entre plusieurs applications.

- Ensuite, générez la bibliothèque dynamique ; à ce stade, ajoutez l'option de l'éditeur de liens -shared.

g++ -shared -o libdynmath.so DynamicMath.o

-shared spécifie la génération d'une bibliothèque de liens dynamiques.

clip_image025[4]

En fait, les deux étapes ci-dessus peuvent être combinées en une seule commande :

g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

3.2.3. Utilisation des bibliothèques dynamiques

Écrivez un code de test qui utilise la bibliothèque dynamique :

Code de test :
#include "../DynamicLibrary/DynamicMath.h"

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << DynamicMath::add(a, b) << endl;
    cout << "a - b = " << DynamicMath::sub(a, b) << endl;
    cout << "a * b = " << DynamicMath::mul(a, b) << endl;
    cout << "a / b = " << DynamicMath::div(a, b) << endl;

    DynamicMath dyn;
    dyn.print();
    return 0;
}

Référencez la bibliothèque dynamique et compilez-le en un fichier exécutable (de la même manière qu'avec une bibliothèque statique) :

g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

Exécutez ensuite : ./a.out, et vous constaterez qu'il signale en fait une erreur !!!

clip_image027[4]

Vous pourriez supposer que c'est parce que la bibliothèque dynamique et le programme de test ne sont pas dans le même répertoire. Vérifions si c'est le cas :

clip_image029[4]

Il signale toujours une erreur !!! Alors, comment les fichiers de bibliothèques partagées sont-ils localisés lors de l'exécution ?

1) Lorsque le système charge du code exécutable, il peut connaître les noms des bibliothèques dont il dépend, mais il doit aussi connaître les chemins absolus. À ce stade, l'éditeur de liens/chargeur dynamique du système est nécessaire.

2) Pour les programmes exécutables au format ELF, cela est effectué par ld-linux.so*. Il parcourt dans l'ordre le segment DT_RPATH du fichier ELF, la variable d'environnement LD_LIBRARY_PATH, la liste du fichier /etc/ld.so.cache, et les répertoires /lib/ et /usr/lib, puis charge le fichier de bibliothèque en mémoire après l'avoir trouvé.

Comment faire pour que le système puisse le trouver :

- S'il est installé sous /lib ou /usr/lib, alors ld peut le trouver par défaut sans aucune opération supplémentaire.

- S'il est installé dans un autre répertoire, vous devez l'ajouter au fichier /etc/ld.so.cache. Les étapes sont les suivantes :

- Modifiez le fichier /etc/ld.so.conf et ajoutez le chemin du répertoire contenant le fichier de bibliothèque.

- Exécutez ldconfig ; cette commande reconstruira le fichier /etc/ld.so.cache.

Nous copions la bibliothèque dynamique créée dans /usr/lib, puis exécutons le programme de test.

clip_image031[4]

3.3. Création et utilisation de bibliothèques dynamiques sous Windows

3.3.1. Création d'une bibliothèque dynamique (.dll)

Comparé à Linux, créer une bibliothèque dynamique sous le système Windows est un peu plus compliqué. Tout d'abord, vous avez besoin d'une fonction DllMain comme point d'entrée d'initialisation (lors de la création d'une application console Win32, la sélection du type DLL générera automatiquement ce fichier) :

fichier d'entrée dllmain.cpp
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Habituellement, lors de la déclaration de fonctions exportées, vous avez besoin du mot-clé _declspec(dllexport) :

Fichier d'en-tête DynamicMath.h
#pragma once
class DynamicMath
{
public:
    __declspec(dllexport) DynamicMath(void);
    __declspec(dllexport) ~DynamicMath(void);

    static __declspec(dllexport) double add(double a, double b);//加法
    static __declspec(dllexport) double sub(double a, double b);//减法
    static __declspec(dllexport) double mul(double a, double b);//乘法
    static __declspec(dllexport) double div(double a, double b);//除法

    __declspec(dllexport) void print();
};

Pour générer une bibliothèque dynamique, vous devez définir les propriétés du projet. Ouvrez les "Pages de propriétés" du projet -> "Propriétés de configuration" -> "Général", et sélectionnez Bibliothèque dynamique pour le Type de configuration.

clip_image033[4]

Figure : v Paramètres des propriétés du projet de bibliothèque dynamique

Générez le projet et la bibliothèque dynamique sera créée.

3.3.2. Utilisation des bibliothèques dynamiques

Créez un programme de test console Win32 :

Programme de test TestDynamicLibrary.cpp
#include "stdafx.h"
#include "DynamicMath.h"

#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << DynamicMath::add(a, b) << endl;
    cout << "a - b = " << DynamicMath::sub(a, b) << endl;
    cout << "a * b = " << DynamicMath::mul(a, b) << endl;
    cout << "a / b = " << DynamicMath::div(a, b) << endl;

    DynamicMath dyn;
    dyn.print();

    system("pause");
    return 0;
}

Méthode 1 :

- Pages de propriétés du projet -> "Propriétés communes" -> "Framework et références" -> "Ajouter une référence" ; la boîte de dialogue "Ajouter une référence" s'affichera. L'onglet "Projets" répertorie les projets de la solution actuelle et toutes les bibliothèques qui peuvent être référencées. Dans l'onglet "Projets", sélectionnez DynamicLibrary. Cliquez sur "OK".

clip_image035[4]

- Ajoutez le répertoire du fichier d'en-tête DynamicMath.h ; vous devez modifier le chemin du répertoire d'inclusion. Ouvrez les "Pages de propriétés" du projet -> "Propriétés de configuration" -> "C/C++" -> "Général". Dans la valeur de propriété "Répertoires d'inclusion supplémentaires", tapez ou parcourez le répertoire contenant le fichier d'en-tête DynamicMath.h.

clip_image037[4]

Compilation et exécution OK.

clip_image038[4]

Figure : Résultats des tests de la bibliothèque dynamique (VS)

Méthode 2 :

- "Pages de propriétés" -> "Propriétés de configuration" -> "Éditeur de liens" -> "Général" ; dans Répertoires de bibliothèques supplémentaires, entrez le répertoire contenant la bibliothèque dynamique.

clip_image040[4]

- "Pages de propriétés" -> "Propriétés de configuration" -> "Éditeur de liens" -> "Entrée" ; dans Dépendances supplémentaires, entrez DynamicLibrary.lib généré par la compilation de la bibliothèque dynamique.

clip_image042[4]

Ici, vous vous posez peut-être une question : pourquoi une bibliothèque dynamique a-t-elle aussi un fichier DynamicLibrary.lib ? C'est-à-dire que, qu'il s'agisse d'une bibliothèque de liens statique ou d'une bibliothèque de liens dynamique, il y a toujours un fichier lib à la fin. Alors, quelle est la différence entre les deux ? En fait, ce sont des choses complètement différentes.

clip_image044[4]

La taille de StaticLibrary.lib est de 190KB, et la taille de DynamicLibrary.lib est de 3KB. Le fichier lib correspondant à une bibliothèque statique est appelé unebibliothèque statique, et le fichier lib correspondant à une bibliothèque dynamique est appelé une [bibliothèque d'importation]. En fait, une bibliothèque statique contient elle-même le code exécutable réel, la table des symboles, etc., tandis quepour une bibliothèque d'importation, le code exécutable réel se trouve dans la bibliothèque dynamique ; la bibliothèque d'importation ne contient que la table des symboles d'adresses et d'autres informations d'adresse de base pour garantir que le programme peut trouver les fonctions correspondantes.。

4. Appel explicite des bibliothèques dynamiques

La méthode d'utilisation des bibliothèques dynamiques présentée ci-dessus est similaire à celle des bibliothèques statiques et relève de l'appel implicite ; au moment de la compilation, la bibliothèque correspondante et le chemin de recherche sont spécifiés. En fait, les bibliothèques dynamiques peuvent également être appelées explicitement.[En langageC], appeler explicitement une bibliothèque dynamique est un jeu d'enfant !

4.1. Appel explicite des bibliothèques dynamiques sous Linux

#include <dlfcn.h> fournit les interfaces suivantes :

- void * dlopen(const char *pathname, int mode) : La fonction ouvre le fichier de bibliothèque de liens dynamiques spécifié dans le mode spécifié et renvoie un handle au processus appelant.

- void* dlsym(void* handle, const char* symbol) : dlsym renvoie l'adresse correspondant au symbole en fonction du handle de bibliothèque de liens dynamiques (pHandle) et du symbole. À l'aide de cette fonction, vous pouvez obtenir non seulement des adresses de fonctions, mais aussi des adresses de variables.

- int dlclose(void *handle) : dlclose est utilisé pour fermer la bibliothèque de liens dynamiques avec le handle spécifié. Ce n'est que lorsque le compteur d'utilisation de cette bibliothèque de liens dynamiques atteint 0 qu'elle est réellement déchargée par le système.

- const char *dlerror(void) : Lorsqu'une fonction d'opération de bibliothèque de liens dynamiques échoue, dlerror peut renvoyer des informations d'erreur. Une valeur de retour NULL indique que la fonction d'opération a été exécutée avec succès.

4.2. Appel explicite de bibliothèques dynamiques sous Windows

Une application doit effectuer un appel de fonction pour charger explicitement la DLL au moment de l'exécution. Pour lier explicitement une DLL, l'application doit :

- AppelerLoadLibrary(ou une fonction similaire) pour charger la DLL et obtenir un handle de module.

- AppelerGetProcAddress, pour obtenir un pointeur de fonction vers chaque fonction exportée que l'application doit appeler. Étant donné que l'application appelle les fonctions de la DLL via des pointeurs, le compilateur ne génère pas de références externes, il n'est donc pas nécessaire de se lier à une bibliothèque d'importation.

- Après avoir utilisé la DLL, appelerFreeLibrary。

4.3. Points à noter lors de l'appel explicite de bibliothèques dynamiques C++

Pour C++, la situation est un peu plus compliquée. La difficulté de charger explicitement une bibliothèque dynamique C++vient en partie dumangling de noms C++;et en partie parce qu'aucuneAPI appropriée n'est fourniepour charger des classes, en C++, vous pouvez avoir besoin d'utiliser une classe de la bibliothèque, ce qui nécessite de créer une instance de cette classe, et ce n'est pas facile à faire.

mangling de nomsCela peut être résolu avec extern "C". C++ dispose d'un mot-clé spécifique utilisé pour déclarer des fonctions avec une liaison C : extern "C". Les fonctions déclarées avec extern "C" utiliseront le nom de fonction comme nom de symbole, tout comme les fonctions C. Par conséquent, seules les fonctions non membres peuvent être déclarées comme extern "C", et elles ne peuvent pas être surchargées. Malgré de nombreuses limitations, les fonctions extern "C" restent très utiles, car elles peuvent être chargées dynamiquement avec dlopen tout comme les fonctions C. Le fait d'avoir le qualificateur extern "C" ne signifie pas que du code C++ ne peut pas être utilisé à l'intérieur de la fonction. Au contraire, c'est toujours une fonction entièrement C++ et elle peut utiliser n'importe quelle fonctionnalité C++ et divers types de paramètres.

De plus, en ce qui concerne la façon d'obtenir des classes à partir de bibliothèques dynamiques C++, voici quelques articles connexes, mais je ne recommande pas de faire ceci :

- "Appel d'une classe dans une DLL avec LoadLibrary" :http://www.cppblog.com/codejie/archive/2009/09/24/97141.html

- 《C++ dlopen mini HOWTO》:http://blog.csdn.net/denny_233/article/details/7255673

L'utilisation « explicite » de classes dans les bibliothèques dynamiques C++ est très lourde et dangereuse ; donc si l'utilisation implicite est possible, ne recourez pas à l'explicite ; si le statique est possible, ne recourez pas au dynamique.

5. Annexe : Commandes liées aux bibliothèques sous Linux

5.1. Options du compilateur g++ (gcc)

- -shared : Indique de générer une bibliothèque de liaison dynamique.

- -static : Indique de générer une bibliothèque de liaison statique.

- -fPIC : Indique une compilation en code indépendant de la position, utilisée pour compiler des bibliothèques partagées. Le fichier objet doit être créé en tant que code indépendant de la position, ce qui signifie conceptuellement que lorsque le programme exécutable les charge, ils peuvent être placés n'importe où dans la mémoire du programme exécutable.

- -L. : Indique le répertoire où se trouve la bibliothèque à lier.

- -l : Spécifie la bibliothèque dynamique nécessaire au moment de la liaison. Le compilateur a une règle de nommage implicite lorsqu'il recherche des bibliothèques de liaison dynamiques, c'est-à-dire ajouter "lib" avant le nom donné et ".a/.so" après celui-ci pour déterminer le nom de la bibliothèque.

- -Wall : Génère tous les messages d'avertissement.

- -ggdb : Cette option générera autant d'informations de débogage utilisables par gdb que possible.

- -g : Le compilateur génère des informations de débogage pendant la compilation.

- -c : Activer uniquement le prétraitement, la compilation et l'assemblage, c'est-à-dire transformer le programme en un fichier objet (fichier .o).

- -Wl,options : Passer les paramètres (options) à l'éditeur de liens ld. Si options contient des virgules, diviser options en plusieurs options, puis les passer au programme d'édition de liens.

5.2. La commande nm

Parfois, vous pouvez avoir besoin de voir quelles fonctions se trouvent dans une bibliothèque.nm, la commande,Elle peut afficher tous les symboles impliqués dans la bibliothèque. La bibliothèque peut être statique ou dynamique. Il y a de nombreux symboles listés par nm, et il existe trois types courants :

- Un type est appelé dans la bibliothèque mais n'est pas défini dans la bibliothèque (ce qui indique qu'un support d'autres bibliothèques est nécessaire), représenté par U ;

- Un type correspond aux fonctions définies dans la bibliothèque, représenté par T, ce qui est le plus courant ;

- Un type correspond aux symboles dits « faibles ». Bien qu'ils soient définis dans la bibliothèque, ils peuvent être remplacés par des symboles portant le même nom dans d'autres bibliothèques, représentés par W.

$nm libhello.h

5.3. La commande ldd

lddLa commande peut afficher les bibliothèques partagées dont dépend un programme exécutable.Par exemple, la bibliothèque dynamique arithmétique que nous avons écrite dépend des bibliothèques suivantes :

clip_image046[4]

6. Résumé

La différence entre les deux estle moment où le code est chargé est différent.。

- Les bibliothèques statiques sont liées dans le code objet lors de la compilation du programme, et la bibliothèque statique ne sera plus nécessaire lors de l'exécution du programme.Par conséquent, la taille est plus grande.。

- Dynamic libraries are not linked into the object code during program compilation, but are loaded only when the program runs. Therefore, the dynamic library needs to exist when the program runs.La taille du code est donc plus petite.。

L'avantage des bibliothèques dynamiques est que si différentes applications appellent la même bibliothèque, une seule instance de la bibliothèque partagée est nécessaire en mémoire. Tout en apportant des avantages, cela pose aussi des problèmes ! Comme le problème classique de l'enfer des DLL. Concernant la manière d'éviter les problèmes de gestion des bibliothèques dynamiques, vous pouvez rechercher vous-même des documents pertinents.

7. Tutoriels connexes

Tutoriel C++ :http://www.w3cschool.cc/cplusplus/cpp-tutorial.html

Auteur : Wu Qin
Source : http://www.cnblogs.com/skynet/