La construction d'une bibliothèque partagée à l'aide de gcc
RÉSOLU. Voir ci-dessous pour les corrections (étiquette FIXE).
Je vais avoir de la difficulté à créer une bibliothèque partagée à l'aide de gcc.
J'ai créé un petit exemple de projet qui correspond étroitement à la structure du projet lui-même, je travaille sur. Je l'ai fait disponibles en tant que tar.gz archive ici:
http://209.59.216.197/libtest.tar.gz
FIXE: j'ai fait la version fixe disponibles ici:
http://209.59.216.197/libtest_fixed.tar.gz
Dans cet exemple de projet, j'ai une application (app) qui charge une bibliothèque partagée que j'ai écrit (libshared.donc) au moment de l'exécution et appelle une fonction de la bibliothèque partagée définit: function_inside_shared_lib().
À son tour, cette bibliothèque partagée utilise une fonction définie à l'intérieur d'une bibliothèque statique (libstatic.a): function_inside_static_lib().
Le problème, c'est quand j'ai construit la bibliothèque partagée, le symbole "function_inside_shared_lib" n'est pas exporté. J'ai examiné la bibliothèque partagée à l'aide de "nm" et le symbole n'était pas là. Je me demandais si la commande j'utilise pour créer la bibliothèque partagée est correct:
g++ -g -ggdb -fPIC-rdynamic -I ../statique -c shared.cpp -o partagé.o
g++ -g -ggdb -fPIC-rdynamic -partagé -L ../statique -lstatic -o libshared.donc
FIXE: Les commandes correctes sont les suivantes:
g++ -g -ggdb -fPIC-rdynamic -I../statique -c shared.cpp -o partagé.o
g++ -g -ggdb -fPIC-rdynamic -partagé -L../statique -o libshared.donc partagé.o -lstatic
J'ai essayé ces commandes avec et sans -rdynamic, ainsi qu'avec et sans l'option-fPIC. Les résultats sont toujours les mêmes.
J'utilise Ubuntu 10.04 (64-bit) avec g++ version 4.4.3.
La totalité de l'échantillon projet suit. (Ou vous pouvez télécharger l'archive en utilisant le lien en haut de mon post).
serg@rongeurs:~/libtest$ ls
app partagé statique
Ici sont les trois composantes:
Composante 1: Une bibliothèque statique qui définit une fonction appelée function_inside_static_lib().
Elle comprend les éléments suivants:
serg@rodent:~/libtest$ cd static/ serg@rodent:~/libtest/static$ ls static.cpp static.h
statique.h
//Header file for the static library
int function_inside_static_lib(int arg1, int arg2);
static.cpp
//Source file for the static library
#include <iostream>
using namespace std;
#include "static.h"
int function_inside_static_lib(int arg1, int arg2)
{
cout << "In function_inside_static_lib()" << endl;
//Return the sum
int result = arg1 + arg2;
return result;
}
Composante 2: Une bibliothèque partagée qui utilise la bibliothèque statique et définit une nouvelle fonction.
serg@rongeurs:~/libtest$ cd partagé
serg@rongeurs:~/libtest/shared$ ls
partagé.rpc
shared.cpp
//The shared library only has one source file.
//The shared library uses the static one.
#include "static.h"
#include <iostream>
using namespace std;
int function_inside_shared_lib(int arg1, int arg2)
{
cout << "In function_inside_shared_lib()" << endl;
cout << "Calling function_inside_static_lib()" << endl;
int result = function_inside_static_lib(arg1, arg2);
return result;
}
Composante 3: Une application qui utilise la bibliothèque partagée.
serg@rongeurs:~/libtest$ cd app
serg@rongeurs:~/libtest/app$ ls
app.rpc
app.cpp
FIXE: Parce que le C++ symboles se déchire, le bon nom de la fonction de recherche est _Z26function_inside_static_libii
au lieu de function_inside_static_lib
//The application loads the shared library at runtime.
#include <dlfcn.h>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
void *handle;
int (*function_inside_shared_lib)(int, int);
char *error;
int arg1 = 3;
int arg2 = 7;
cout << "app: loading the shared library." << endl;
handle = dlopen ("libshared.so", RTLD_LAZY);
if (!handle) {
cout << "Error: Failed to open shared library." << endl;
cout << dlerror() << endl;
return -1;
}
cout << "app: Looking for function_inside_shared_lib" << endl;
//The next line is now FIXED:
function_inside_shared_lib = (int (*)(int, int))dlsym(handle, "_Z26function_inside_static_libii");
if ((error = dlerror()) != NULL) {
cout << "Error: Could not find the function." << endl;
cout << error << endl;
return -1;
}
cout << "app: Calling function_inside_shared_lib(" << arg1 << ", " << arg2 << ")" << endl;
int result = (*function_inside_shared_lib)(arg1, arg2);
cout << "app: The result is " << result << endl;
dlclose(handle);
return 0;
}
Voici les commandes que j'utilise pour construire l'ensemble de ces composants. Notez que je veux les symboles de débogage pour être disponible dans le final de l'application. Idéalement, je veux être capable de faire une trace à l'intérieur de l'application et de voir les symboles de la fois la bibliothèque partagée et la bibliothèque statique.
1: la Construction de la bibliothèque statique. Je pense que je suis à l'aise avec cette étape:
serg@rongeurs:~/libtest/static$ g++ -g -ggdb -c static.cpp -o statique.o # Voir la version FIXE juste en dessous
serg@rongeurs:~/libtest/static$ ar rcs libstatic.un statique.o
serg@rongeurs:~/libtest/static$ ls
libstatic.un static.cpp statique.h statique.o
FIXE: La première commande ci-dessus doit comporter-fPIC. Le bon de commande est
g++ -g -ggdb -fPIC-c static.cpp -o statique.o
2: la Construction de la bibliothèque partagée. Je suis sûr que c'est là que je vais mal.
serg@rongeurs:~/libtest/shared$ g++ -g -ggdb -fPIC-rdynamic -I ../statique -c shared.cpp -o partagé.o
serg@rongeurs:~/libtest/shared$ g++ -g -ggdb -fPIC-rdynamic -partagé -L ../statique -lstatic -o libshared.donc, # Voir juste ci-dessous pour la version FIXE
serg@rongeurs:~/libtest/shared$ ls
libshared.donc shared.cpp partagé.o
FIXE: La deuxième commande ci-dessus doivent être:
g++ -g -ggdb -fPIC-rdynamic -partagé -L../statique -o libshared.donc partagé.o -lstatic
À ce point, si je run nm pour examiner les symboles à l'intérieur de libshared.donc, je ne vois pas function_inside_shared_lib() n'importe où, même avec l'-et -D options pour nm. (Cependant, je ne voir à l'intérieur partagée.o).
EDIT: Avec le correctif ci-dessus, le symbole apparaît comme _Z26function_inside_shared_libii
.
3: la Construction de l'application:
Tout d'abord, copiez la bibliothèque partagée dans le dossier app:
serg@rongeurs:~/libtest$ cp partagé/libshared.donc app/
serg@rongeurs:~/libtest$ cd app
serg@rongeurs:~/libtest/app$ ls
app.rpc libshared.donc
Maintenant compiler:
serg@rongeurs:~/libtest/app$ g++ -g -ggdb -ldl -L. -lshared app.cpp -o app
serg@rongeurs:~/libtest/app$ ls
app app.cpp libshared.donc
Si j'essaie de le lancer:
serg@rongeurs:~/libtest/app$ ./app
app: le chargement de la bibliothèque partagée.
application: la Recherche d'function_inside_shared_lib
Erreur: impossible de trouver la fonction.
/home/serg/libtest/app/libshared.so: undefined symbol: function_inside_shared_lib
Cela a un sens parce que je ne pouvais pas voir function_inside_shared_lib() à l'aide de nm, ce qui signifie que je suis probablement la construction de la bibliothèque partagée de manière incorrecte à l'étape 2.
Comment puis-je réparer ma commande dans la deuxième étape, de sorte que function_inside_shared_lib est exporté correctement?
Aussi n'hésitez pas à me donner d'autres conseils si vous remarquez que je suis en train de faire quelque chose de bizarre. Je suis encore un débutant.
La commande pour la construction de l'objet partagé de bibliothèque n'a pas l'air de droit -, il ne mentionne pas partagé.o. Avez-vous tapé correctement?
Est-ce une question ou dix-sept questions ou des dix-sept réponses? Je ne peux pas en dire plus...
Question similaire - stackoverflow.com/questions/14884126/...
OriginalL'auteur Sergey K | 2010-08-27
Vous devez vous connecter pour publier un commentaire.
Il y a quelques erreurs ici:
libshared.donc est vide
Votre Makefile n'a pas de lien dans la commune.o , il crée un vide bibliothèque partagée.
Changement
à
L'-lstatic venir après partagée et à partager.o que vous devez spécifier les bibliothèques statiques dans l'ordre inverse de leurs dépendances.
-fPIC est nécessaire à tous les fichiers de l'objet dans une bibliothèque partagée
Vous créer une bibliothèque partagée que les liens dans une bibliothèque statique. Cette bibliothèque statique aussi être compilé avec-fPIC, sinon vous êtes en train de créer une bibliothèque partagée où certains éléments ne peuvent pas être déplacés. Changement
à
Symboles C++ se déchire
Que vous êtes en train de créer une bibliothèque partagée à partir de code C++, les noms de fonction et similaires obtient mangeled
Cela signifie qu'il n'existe pas de fonction de correspondance de nom de la chaîne "function_inside_static_lib" que vous essayez de charger dynamiquement. run nm sur la statique de la bibliothèque, vous verrez qu'il est en fait le nom "_Z26function_inside_static_libii" . Vous pouvez exécuter nm -C pour pretty print C++ noms.
Cela signifie que votre code dans app.cpp être:
C'est l'une des raisons pour laquelle il est souvent préférable d'exportation de fonctions à partir d'objets partagés à l'aide de C au lieu de C++ si vous voulez dynamiquement (dlopen) va chercher quelque chose à partir d'une bibliothèque partagée. Le C++ name mangling ont, dans le passé, a varié de compilateur de compilateur, bien que ces jours, ils semblent tous d'accord sur un standard qui ne sera pas en train de changer. Avec le C, c'est plus simple, et les symboles dans la bibliothèque partagée sera le même que vous leur avez donné dans votre code source.
OriginalL'auteur nos
Donc, dans l'étape 2 vous ne spécifiez pas partagé.o. Ainsi, au lieu de:
Que vous devez faire:
Il est également important que partagé.o est avant -lstatic. Sinon, l'éditeur de liens ne sera pas trouver la fonction et le laisser 'undefined'.
OriginalL'auteur vladmihaisima