2010-04-06 4 views
6

Basé sur this question Je comprends le but de la construction dans la liaison des bibliothèques C avec le code C++. Supposons maintenant ce qui suit:Quel est l'effet de la déclaration de «extern» C "'dans l'en-tête d'une bibliothèque partagée C++?

J'ai une bibliothèque partagée '.so' compilée avec un compilateur C++. L'en-tête a un 'typedef stuct' et un certain nombre de déclarations de fonctions. Si l'en-tête comprend la déclaration extern "C" ...

#ifdef __cplusplus 
extern "C" 
{ 
#endif 

    // typedef struct ...; 
    // function decls 

#ifdef __cplusplus 
} 
#endif 

... quel est l'effet? Plus précisément, je me demande s'il y a des effets secondaires néfastes de cette déclaration puisque la bibliothèque partagée est compilée en C++, pas C.

Y a-t-il une raison d'avoir la déclaration externe "C" dans ce cas?

+0

Votre bibliothèque sera-t-elle seulement appelée depuis C++ ou avez-vous besoin de votre bibliothèque pour être appelée depuis C? –

Répondre

11

Ceci est important pour que le compilateur ne nomme pas mangle. C++ utilise le nom mangling pour différencier les fonctions avec les surcharges d'opérateurs.

Exécuter "/ usr/bin/nm" contre un binaire pour voir ce que C++ fait avec vos noms de fonction: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

extern "C" empêche ce nom mutiler. IIRC, qui permet au programme de lier dynamiquement des symboles lors de l'exécution. C'est commun pour les architectures de type "plugin".

+0

Merci pour l'info.Je pensais à ce point de vue le client, y compris l'en-tête, et non la bibliothèque qui exporte les noms. –

4

Lors de la compilation C++ les Changements de nom de la méthode (mutiler) - et vous ne serez pas en mesure d'appeler cette méthode à partir d'une autre dll/exe qui utilise C.

Afin de garder le nom de la classe et la méthode dont vous avez besoin pour les compiler comme "C" sans nom mangling.

La bibliothèque est toujours une bibliothèque C++ mais elle expose certaines de ses déclarations (celle du bloc "c" externe) en tant que méthodes C.

3

La déclaration extern gardée extern est de dire aux lieurs C que les symboles ont des entrées de table de symboles C (non mélangées). Le #ifdef garantit qu'il n'y a aucun effet dans l'unité de code (fichier) compilée par un compilateur C.

0

un préjudice à l'utilisation extern "C" pour une API C++ est qu'il vous empêche d'avoir des surcharges de fonction:

extern "C" 
{ 
    // ILLEGAL - C linkage does not support function overloading 
    void foo(int x); 
    void foo(const char *str); 
} 
+1

Le point d'utiliser 'extern « C »' est à la fois le code C et C++ pour partager une API, et C est le plus petit dénominateur commun, vous devez respecter les règles que le compilateur C applique. Si * était * une API C++, alors vous n'utiliseriez pas "extern" C "' et ne compileriez qu'avec un compilateur C++ et tout irait bien. – quamrana

+1

@quamrana - et sa question est « quel est l'effet d'un C++ de bibliothèque partagée ». Il n'est pas clair à partir de la question s'il doit être capable d'appeler sa bibliothèque à partir du code C. –

0

Le #ifdef dans l'exemple signifie que seul un compilateur C++ verra le extern enveloppant le fichier d'en-tête qui signifiera qu'il produira des noms non mutilés. Un compilateur C ne voit pas le extern (qu'il ne comprendrait pas), mais produit toujours des noms non mutilés. Cela signifie que les compilateurs C et C++ produiront les mêmes symboles dans leurs fichiers objets. Ainsi, quel que soit le compilateur produisant le code objet pour les fonctions déclarées, tous les fichiers objets seront liés car les symboles ont le même lien et le même nom .

Il ne devrait pas y avoir d'implications pour la liaison statique ou la liaison avec une bibliothèque partagée.

Questions connexes