Extern “C” est-il uniquement requirejs dans la déclaration de fonction?

J’ai écrit une fonction C ++ que j’ai besoin d’appeler à partir d’un programme C. Pour le rendre appelable à partir de C, j’ai spécifié extern "C" dans la déclaration de fonction. J’ai ensuite compilé le code C ++, mais le compilateur (Dignus Systems / C ++) a généré un nom mutilé pour la fonction. Donc, il n’a apparemment pas honoré l’ extern "C" .

Pour résoudre ce problème, j’ai ajouté extern "C" à la définition de la fonction. Après cela, le compilateur a généré un nom de fonction appelable à partir de C.

Techniquement, l’ extern "C" doit uniquement être spécifié dans la déclaration de fonction. Est-ce correct? (La FAQ FAQ C ++ en fournit un bon exemple.) Devriez-vous également l’indiquer dans la définition de la fonction?

Voici un exemple pour illustrer ceci:

 /* ---------- */ /* "foo.h" */ /* ---------- */ #ifdef __cplusplus extern "C" { #endif /* Function declaration */ void foo(int); #ifdef __cplusplus } #endif /* ---------- */ /* "foo.cpp" */ /* ---------- */ #include "foo.h" /* Function definition */ extern "C" // <---- Is this needed? void foo(int i) { // do something... } 

Mon problème peut résulter d’un code incorrect, ou j’ai peut-être trouvé un bogue du compilateur. Dans tous les cas, je voulais consulter stackoverflow pour être sûr de savoir quelle est techniquement la “bonne” façon.

Le ” extern "C" ne devrait pas être requirejs dans la définition de fonction aussi longtemps que la déclaration le contient et est déjà visible dans la compilation de la définition. La norme indique spécifiquement (7.5 / 5 spécifications de liaison):

Une fonction peut être déclarée sans spécification de liaison après avoir vu une spécification de liaison explicite; le lien explicitement spécifié dans la déclaration antérieure n’est pas affecté par une telle déclaration de fonction.

Cependant, je mets généralement le ” extern "C" sur la définition également, car il s’agit en fait d’une fonction avec un lien externe “C”. Beaucoup de gens détestent quand des choses inutiles et redondantes sont sur des déclarations (comme mettre virtual substitutions de méthodes virtual sur des méthodes), mais je n’en fais pas partie.

Modifier:
On dirait que j’ai mal compris la question. Quoi qu’il en soit, j’ai essayé:

 // foo.cpp /* Function definition */ #include "foo.h" void foo(int i) { //do stuff } void test(int i) { // do stuff } // foo.h #ifdef __cplusplus extern "C" { #endif /* Function declaration */ void foo(int); #ifdef __cplusplus } #endif void test(int); 

Utilisation de la commande nm pour afficher les symboles du fichier compilé:

 linuxuser$ nm foo.o 00000006 T _Z4testi U __gxx_personality_v0 00000000 T foo 

Ceci suggère clairement que le nom de la fonction déclarée comme extern “C” n’est pas mutilé et que le mot clé extern “C” n’est pas requirejs à la définition.
Si cela avait été nécessaire, chaque code de bibliothèque C écrit sans extern “C” aurait été inutilisable dans les programmes C ++.

Juste rencontré cette situation … Pas une expérience agréable.

Ce qui suit a été déclaré dans l’un de mes fichiers c :

 void unused_isr(void) {} void ADC_IRQHandler(void) __atsortingbute__ ((weak, alias("unused_isr"))); 

Suivant quelque part dans un fichier cpp j’ai défini:

 void ADC_IRQHandler(void) { ... } 

Et j’ai oublié de changer la déclaration suivante en:

 void ADC_IRQHandler(void); 

Il m’a fallu un certain temps avant de comprendre que je faisais bien tout ce qui était en ce qui concerne la conversion AD, mais je n’ai pas réussi à append “extern C” à la définition!

 extern "C" void ADC_IRQHandler(void) { ... } 

Juste mes deux cents pourquoi il pourrait être utile dans certaines circonstances d’avoir l’habitude de l’append également à la définition.

Je pense que ceci doit être clarifié ici, étant donné que je viens d’avoir un problème similaire et qu’il m’a fallu un certain temps pour bien comprendre cela, seul Brooks Moses en a parlé correctement et je pense que cela doit être exposé plus clairement. .

En résumé, l’en-tête peut vous décourager, tout ce que le compilateur voit est le fichier cpp et si l’en-tête n’est pas inclus avec l’externe “C” dans votre cpp (ce que je vois couramment), alors l’externe “C” devra être dans le fichier cpp quelque part (soit dans la définition, soit dans une autre déclaration) pour que le compilateur CXX sache le créer avec une liaison C, le compilateur ne se soucie pas de l’en-tête, mais uniquement de l’éditeur de liens.

Le extern "C" autour de la définition n’est pas requirejs. Vous pouvez vous en tirer simplement en contournant la déclaration. Une note dans votre exemple …

 #ifdef __cplusplus extern "C" { #endif /* Function declaration */ void foo(int); #ifdef __cplusplus } #endif 

Votre code recherche la macro de préprocesseur ” __cplusplus “.

Bien que cela soit généralement implémenté, cela peut être défini ou non, selon votre compilateur. Dans votre exemple, vous utilisez également extern "C" autour de la déclaration, mais vous ne recherchez pas la macro ” __cplusplus “, raison pour laquelle je suppose que cela a fonctionné une fois que vous l’avez fait.

Voir les commentaires ci-dessous – Le standard C ++ requirejs que la macro __cplusplus soit définie par le préprocesseur.

Il devrait être autour des deux. Le compilateur doit savoir utiliser le nom du symbole C et les conventions d’appel lors de la compilation des sites d’appel (qui ne peuvent voir qu’une déclaration). Il doit également savoir comment générer le nom du symbole C et utiliser les conventions d’appel C lors de la compilation. définition de la fonction elle-même (qui peut ne voir aucune autre déclaration).

Maintenant, si vous avez une déclaration extern-C qui est visible depuis l’unité de traduction dans laquelle la définition existe, vous pourrez peut-être vous en sortir en laissant de côté l’extern-C de la définition, mais je ne suis pas sûr que .