Question

J'ai un problème avec mon compilateur qui me dit qu'il existe une "référence non définie à" une fonction que je veux utiliser dans une bibliothèque. Permettez-moi de partager quelques informations sur le problème:

  • Je compile avec gcc pour C.
  • J'appelle une fonction de bibliothèque à laquelle on accède via un en-tête inclus, qui comprend un autre en-tête, qui contient le prototype.
  • J'ai inclus le répertoire des en-têtes avec -I et je suis sûr qu'il est trouvé.
  • Je crée d'abord les fichiers .o, puis les relie dans une commande séparée.

Donc, ma pensée est que cela pourrait être l'ordre dans lequel j'inclus les fichiers de bibliothèque, mais je ne sais pas quelle est la bonne façon de les commander. J'ai essayé d'inclure le dossier des en-têtes avant et après le fichier .o.

Certains suggèrent que ce serait bien, et peut-être une explication de la façon dont l’éditeur de liens fait son travail.

Merci!

Réponse aux réponses

  • il n'y a pas de fichier de bibliothèque .a, seulement .h et .c dans la bibliothèque, donc -l n'est pas approprié
  • D'après ce que je sais d'un fichier de bibliothèque, il ne s'agit que d'une collection de fichiers d'en-tête et de fichiers sources, mais peut-être s'agit-il d'une collection de fichiers .o créés à partir de la source?!
  • il n'y a pas de fichier d'objet de bibliothèque en cours de création, peut-être qu'il devrait y en avoir ?? Oui, apparemment, je ne comprends pas la différence entre les inclus et les bibliothèques ... Je vais y travailler: -)

Merci pour toutes les réponses! J'ai beaucoup appris sur les bibliothèques. Je voudrais mettre toutes les réponses comme la réponse acceptée: -)

Était-ce utile?

La solution

On dirait que vous ne compilez pas le fichier .c dans la bibliothèque pour produire un fichier .o. L’éditeur de liens chercherait l’implémentation du prototype dans le fichier .o produit en compilant la bibliothèque

Votre processus de construction compile-t-il le fichier .c de la bibliothèque?

Pourquoi l’appelez-vous une "bibliothèque"? si c'est en fait juste du code source?

Autres conseils

Les en-têtes fournissent les déclarations de fonction et les définitions de fonction. Pour permettre à l'éditeur de liens de rechercher l'implémentation de la fonction (et de supprimer la référence indéfinie), vous devez demander au pilote du compilateur (gcc) de lier la bibliothèque spécifique dans laquelle la fonction réside à l'aide de l'indicateur -l. Par exemple, -lm va lier la bibliothèque mathématique. La page de manuel d’une fonction spécifie généralement quelle bibliothèque, le cas échéant, doit être spécifiée pour rechercher la fonction.

Si l'éditeur de liens ne peut pas trouver une bibliothèque spécifiée, vous pouvez ajouter un chemin de recherche de bibliothèque à l'aide du commutateur -L (par exemple, -L / usr / local / lib). Vous pouvez également affecter de manière permanente le chemin de la bibliothèque via la variable d’environnement LIBRARY_PATH.

Voici quelques détails supplémentaires pour vous aider à résoudre votre problème. Par convention, les noms des fichiers de bibliothèque portent le préfixe lib et (sous leur forme statique) ont une extension .a. Ainsi, la version liée de manière statique de la bibliothèque mathématique par défaut du système (celle que vous liez avec -lm) se trouve généralement dans /usr/lib/libm.a. Pour voir quels symboles une bibliothèque donnée définit, vous pouvez exécuter nm --defined-only sur le fichier de bibliothèque. Sur mon système, l’exécution de la commande sur libm.a me donne les résultats suivants:

e_atan2.o:
00000000 T atan2

e_asinf.o:
00000000 T asinf

e_asin.o:
00000000 T asin

Pour voir le chemin d'accès à la bibliothèque utilisé par votre compilateur et les bibliothèques qu'il charge par défaut, vous pouvez appeler gcc avec l'option -v. Encore une fois sur mon système, cela donne la sortie suivante.

GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd) 
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o 
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc 
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o

Je crains que vous n'ayez mélangé les concepts de bibliothèque et d'en-tête. Supposons que vous avez une bibliothèque libmylib.a qui contient la fonction myfunc () et un en-tête correspondant mylib.h qui définit son prototype. Dans votre fichier source myapp.c , vous incluez l'en-tête, directement ou avec un autre en-tête qui l'inclut. Par exemple:

/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...

votre fichier source ressemble à:

/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");

Vous pouvez maintenant le compiler pour obtenir myapp.o :

gcc -c -I../mylib/includes myapp.c

Notez que le -I dit simplement à gcc où sont les fichiers d'en-tête, ils n'ont rien à voir avec la bibliothèque elle-même!

Vous pouvez maintenant lier votre application à la vraie bibliothèque:

gcc -o myapp -L../mylib/libs myapp.o -lmylib

Notez que le commutateur -L indique à gcc où se trouve la bibliothèque et que le -l lui indique de lier votre code à la bibliothèque.

Si vous ne faites pas cette dernière étape, vous pouvez rencontrer le problème que vous avez décrit.

Il pourrait y avoir d'autres cas plus complexes, mais d'après votre question, j'espère que cela suffira à résoudre votre problème.

Publiez votre makefile et la fonction de bibliothèque que vous essayez d’appeler. Même les makefiles simples de gcc ont généralement une ligne comme celle-ci:

LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared

Dans ce cas, cela signifie de lier la bibliothèque C standard, entre autres

Je suppose que vous devez ajouter le chemin où l'éditeur de liens peut trouver la bibliothèque. Dans gcc / ld, vous pouvez le faire avec -L et libraray avec -l.

  

-Ldir, --library-path = dir

     

Répertoire de recherche dir avant standard   répertoires de recherche (cette option doit   précéder l'option -l qui recherche   ce répertoire).

     

-larch, --library = archive

     

Inclure l'archive du fichier d'archive dans le   liste des fichiers à lier.

  

Réponse aux réponses - il n'y a pas de fichier de bibliothèque .a, mais seulement .h et .c dans la bibliothèque, donc -l n'est pas approprié

Ensuite, vous devrez peut-être créer la bibliothèque en premier?

gcc -c mylib.c -o mylib.o
ar  rcs libmylib.a      mylib.o

J'ai rencontré ce problème lors de la construction d'un programme avec une nouvelle version de gcc. Le problème a été résolu en appelant gcc avec l'option -std = gnu89. Apparemment, cela était dû aux déclarations de fonction inline. J'ai trouvé cette solution à l'adresse https://gcc.gnu.org/gcc-5/porting_to. .html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top