web-dev-qa-db-fra.com

références c ++ non définies avec bibliothèque statique

J'essaie de créer une bibliothèque statique à partir d'une classe, mais lorsque j'essaie de l'utiliser, j'obtiens toujours des erreurs avec des références non définies sur quoi que ce soit. La façon dont j'ai procédé était de créer le fichier objet comme

g++ -c myClass.cpp -o myClass.o

puis l'emballer avec

ar rcs myClass.lib myClass.o

Il y a quelque chose qui me manque évidemment de façon générale. Je parie que c'est quelque chose avec des symboles. Merci pour tout conseil, je sais que c'est probablement quelque chose que je pourrais découvrir si je lis un tutoriel, donc désolé si vous vous embêtez à nouveau avec des trucs stupides :)

éditer:

myClass.h:

class myClass{
    public:
        myClass();
        void function();
};

myClass.cpp:

#include "myClass.h"

myClass::myClass(){}
void myClass::function(){}

programme utilisant la classe:

#include "myClass.h"

int main(){
myClass mc;
mc.function();

return 0;
}

enfin je le compile comme ceci:

g++ -o main.exe -L. -l myClass main.cpp

l'erreur est juste classique:

C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x31): undefined
 reference to `myClass::myClass()'
C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x3c): undefined
 reference to `myClass::function()'
collect2: ld returned 1 exit status
46
Pyjong

C'est probablement un problème d'ordre des liens. Lorsque l'éditeur de liens GNU voit une bibliothèque, il supprime tous les symboles dont il n'a pas besoin. Dans ce cas, votre bibliothèque apparaît avant votre fichier .cpp, donc la bibliothèque est supprimée avant le. Le fichier cpp est compilé. Procédez comme suit:

g++ -o main.exe main.cpp -L. -lmylib

ou

g++ -o main.exe main.cpp myClass.lib

L'éditeur de liens Microsoft ne prend pas en compte l'ordre des bibliothèques sur la ligne de commande.

111
mch

Une autre cause possible: oublier extern "C".

J'ai rencontré cela parce que j'essayais de lier un programme C++ avec une bibliothèque statique C. L'en-tête de la bibliothèque n'avait pas extern "C" donc l'éditeur de liens recherchait un nom de fonction altéré, et la bibliothèque avait en fait le nom de fonction non mélangé.

Il a fallu un certain temps pour comprendre ce qui se passait, alors j'espère que cela aide quelqu'un d'autre.

20
tprk77

C'est un problème de savoir comment l'éditeur de liens optimise le code de sortie. Supposons que nous ayons un exécutable qui utilise deux bibliothèques: Lib_A et Lib_B. Lib_A dépend de Lib_B Le Lib_A définit les symboles: Lib_A1 et Lib_A2 , et le Lib_B définit le symbole Lib_B1 et Lib_B2 . Supposons maintenant que l'exécutable utilise uniquement le symbole Lib_A1 , et Lib_A1 utilise symbole Lib_B1 qui est défini dans Lib_B. Le symbole Lib_B1 n'est jamais utilisé dans l'exécutable.

  1. Dans le cas de Windows, l'éditeur de liens fonctionne comme ceci: j'ai un exécutable avec deux qui utilise des bibliothèques et tous les symboles utilisés dans l'exécutable et toutes les bibliothèques sont lib_A1 et lib_B1 . J'aurai donc besoin de ces deux symboles, et le reste est inutile. Je vais définir lib_A2 et lib_B2
  2. Dans le cas de Linux si vous liez Lib_B avant Lib_A comme ceci: g++ .... -lLib_B -lLib_A L'éditeur de liens fonctionne comme ceci: j'ai un exécutable qui lie d'abord Lib_B. Je ne vois pas que l'exécutable utilise le symbole Lib_B1 ni Lib_B2 . Ils ne sont pas nécessaires, je vais donc les définir. Plus tard, l'éditeur de liens voir. Oh, j'ai une autre bibliothèque Lib_A. Je peux voir que l'exécutable utilise le symbole Lib_B1 . Je vais le conserver et définir le symbole inutilisé Lib_B2 . Il ne voit pas que Lib_B1 utilise Lib_A1 , qui est déjà indéfini.
  3. Dans le cas de Linux si vous liez Lib_A avant Lib_B comme ceci: g++ ... -lLib_A -lLib_B L'éditeur de liens fonctionne comme ceci: j'ai un exécutable qui lie d'abord Lib_A. Oh, je peux voir que l'exécutable utilise Lib_A1 . Je vais les conserver et les définir Lib_A2 . Plus tard, il peut voir. Oh, j'ai une autre bibliothèque Lib_B. Je peux voir que maintenant exécutable avec des symboles déjà liés, utilise Lib_B1 , je vais les garder. En conséquence, il conserve Lib_B1 et Lib_A1 , et indéfini Lib_B2 et Lib_A2 .
6
Grzegorz Dymek

Utilisation:

g++ -o main.exe main.cpp myClass.lib 

L'utilisation du chemin d'accès à la bibliothèque et de l'option -l est lourde de problèmes, mais si vous devez le faire, renommez votre bibliothèque en libmylib.a, puis compilez comme:

g++ -o main.exe main.cpp -L. -lmylib 

Notez également que pour des raisons de portabilité, c'est généralement une mauvaise idée d'utiliser la casse mixte dans les noms des fichiers source ou de sortie.

5
anon

Cela devrait éviter les erreurs de liaison et créer la bibliothèque partagée .so:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
1
Oshi