23 votes

La bibliothèque C ne se lie pas en utilisant gcc/g++

J'ai une bibliothèque c que j'utilise dans gcc. La bibliothèque a l'extension .lib mais est toujours liée en tant que bibliothèque statique. Si j'écris un programme qui utilise la bibliothèque en tant que code c, tout va bien. Si je renomme cependant le fichier en .cpp (en faisant des choses simples qui fonctionnent à la fois en c/c++), j'obtiens une référence indéfinie. Ce sont de simples petits programmes que j'écris à des fins de test donc rien de compliqué. Je compile en utilisant :

gcc -g -Wall -I  -o program main.c customlibrary.lib -lm -lpthread

Le code ci-dessus fonctionne à merveille. Cependant :

g++ -g -Wall -I  -o program main.cpp customlibrary.lib -lm -lpthread

ou

gcc -g -Wall -I  -o program main.cpp customlibrary.lib -lm -lpthread -lstdc++

résulte en une référence indéfinie à n'importe quelle fonction dans customlibrary.lib. J'ai essayé de créer un lien symbolique nommé customlibrary.a mais sans succès.

Pourquoi g++ ne reconnaît-il pas ma bibliothèque ? Malheureusement, je n'ai pas accès au code source des bibliothèques, mais lier une bibliothèque c à du c++ ne devrait pas poser de problème, n'est-ce pas ?

41voto

RBerteig Points 23331

Votre bibliothèque semble avoir une API qui suppose qu'elle sera appelée depuis C, et non depuis C++. C'est important car en C++, il est nécessaire que les symboles exportés d'une bibliothèque contiennent plus d'informations que simplement le nom de la fonction. Cela est géré par la "mangling" des noms des fonctions.

Je suppose que votre bibliothèque possède un fichier d'inclusion qui déclare son interface publique. Pour la rendre compatible à la fois avec C et C++, vous devriez indiquer à un compilateur C++ que les fonctions qu'il déclare doivent être supposées utiliser la liaison et le nommage de C.

Une réponse probablement simple pour tester cela est de faire ceci :

extern "C" {
#include "customlibrary.h"
}

dans votre main.cpp au lieu d'inclure directement customlibrary.h.

Pour que l'en-tête lui-même fonctionne dans les deux langues et déclare correctement ses fonctions comme étant de type C pour C++, placez ce qui suit près du haut du fichier d'en-tête :

#ifdef __cplusplus
extern "C" {
#endif

et ce qui suit près du bas :

#ifdef __cplusplus
}
#endif

4voto

Le compilateur C++ effectue ce qu'on appelle le name-mangling - les noms qui apparaissent dans votre code ne sont pas les mêmes que ceux que votre linker voit. La façon normale de contourner cela est d'indiquer au compilateur que certaines fonctions ont besoin d'une liaison en C :

// myfile.cpp
extern "C" int libfun();    // Fonction C dans votre bibliothèque

ou le faire pour un fichier d'en-tête entier :

// myfile.cpp
extern "C" {
  #include "mylibdefs.h"      // Définitions pour vos fonctions de bibliothèque C
}

2voto

laalto Points 50581

Votre fichier d'en-tête contient-il le code habituel

#ifdef __cplusplus
extern "C" {
#endif

// ...

#ifdef __cplusplus
} /* extern "C" */
#endif

pour donner explicitement le lien C aux fonctions de la bibliothèque.

Les fichiers .cpp sont compilés avec un lien C++ par défaut, c'est-à-dire un mélange de noms de manière automatique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X