Est extern “C” requis uniquement sur la déclaration de la fonction?
J'ai écrit une fonction C++ que j'ai besoin d'appeler à partir d'un programme C. Pour faire appelables à partir de C, j'ai précisé que extern "C"
sur la fonction déclaration. J'ai ensuite compilé le code C++, mais le compilateur (Dignus Systèmes/C++) a généré un nom décomposé pour la fonction. Donc, il n'a apparemment pas l'honneur de la extern "C"
.
Pour résoudre ce problème, j'ai ajouté extern "C"
à la fonction définition. Après cela, le compilateur a généré un nom de fonction qui est appelée à partir de C.
Techniquement, le extern "C"
ne doit être spécifié sur la déclaration de la fonction. Est-ce exact? (Le C++ FAQ Lite a un bon exemple de cela.) Si vous spécifiez également sur la définition de la fonction?
Voici un exemple pour le démontrer:
/* ---------- */
/* "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...
}
Ma question est peut-être le résultat d'une mauvaise codage quelque chose, ou j'ai peut-être trouvé un bogue du compilateur. En tout cas, je voulais consulter stackoverflow pour faire sûr que je connais qui est, techniquement, le "droit" chemin.
- Êtes-vous certains que vous obtenez en fait la déformation de foo, si vous laissez au large de la extern "C" foo.c dans l'exemple de code vous montrer? Ou était-ce juste quelque chose qui s'est produite dans d'autres plus compliquées code? J'ai assez souvent vu ce problème comme un symptôme de l'oubli d'inclure des foo.h foo.c.
- Moïse: C'est un très bon point. Dans mon code, qui est un peu plus complexe que cela "toto" par exemple, je suis y compris l'en-tête dans le "rpc" fichier source. Ce qui m'a fait penser que le compilateur est une déformation du nom était ceci: Si je ne comprend pas le " extern "C" sur la définition de la fonction, alors le compilateur liste affiche le symbole externe, "foo_FPFPCc_v". Lorsque le " extern "C" " est inclus, la liste affiche le symbole externe, "foo".
- il pourrait être intéressant d'expérimenter avec ce que le compilateur ne avec votre exemple simplifié. Si elle montre le même comportement, alors vous pourriez souhaitez envoyer une note pour le vendeur. Si ce n'est pas la même, alors vous devriez suivre ce qui se passe dans votre vraie construire, parce que ce serait indiquer que le tort de l'en-tête est apporté (ou quelque chose d'autre est de faire la déclaration de la fonction manquer).
- Burr - C'est un bon point que cela pourrait être une accumulation de problème (par exemple, certains autres en-tête est arriver inclus, etc.). Je vais vous donner que d'essayer, et si j'apprends quelque chose de nouveau qui pourrait être utile à d'autres, je vais poster un commentaire ici. Merci!
Vous devez vous connecter pour publier un commentaire.
Le "
extern "C"
" ne devrait pas être nécessaire sur la fonction de définition, tant que la déclaration a et est déjà vu lors de la compilation de la définition. La norme précise (7.5/5 de Liaison, cahier des charges):Cependant, en général, je dois mettre le "
extern "C"
" sur la définition, parce que c'est en fait une fonction de liaison extern "C". Beaucoup de gens détestent quand elles sont inutiles, redondants truc est sur les déclarations (comme mettrevirtual
sur les substitutions de méthode), mais je ne suis pas l'un d'eux.virtual
sur les substitutions de méthode 🙂Edit:
Semble que j'avais mal compris la question.
De toute façon, j'ai essayé:
L'aide de la commande
nm
pour afficher les symboles du fichier compilé:Cette montre clairement que le nom de la fonction déclarée comme extern "C" n'est pas de déformation et de la extern "C" mot-clé n'est pas nécessaire à la définition.
Il avait exigé que chaque bibliothèque C du code écrit sans extern "C" aurait été inutilisable dans les programmes C++.
Juste rencontré cette situation... Pas une expérience agréable.
La suite a été déclaré dans l'une de mes
c
fichiers:Prochaine, quelque part dans une
cpp
fichier que j'ai défini:Et j'ai oublié de changer la déclaration anticipée d':
Il m'a fallu un certain temps avant que je compris que je faisais tout droit à l'égard de l'ANNONCE de la conversion, mais je n'ai pas réussi à ajouter "extern C" à la définition de!
Juste mes deux cents pourquoi il pourrait être utile, dans certaines circonstances, d'avoir l'habitude d'ajouter à la définition ainsi.
Je pense que cela doit être précisé ici, que j'ai juste eu un problème similaire et il m'a fallu un certain temps pour obtenir ce clair dans ma tête, seulement Brooks Moïse touché correctement, et je pense qu'elle doit être indiqué plus clairement ...
En résumé l'en-tête peut vous jeter hors, tout le compilateur voit, c'est le fichier cpp et si l'en-tête n'est pas inclus avec la extern "C" dans votre rpc (que j'ai souvent les voir), puis la extern "C" doivent être dans le fichier cpp quelque part (que ce soit dans la définition, ou toute autre déclaration) de sorte que le CXX compilateur ne peut pas savoir le faire avec une liaison C, le compilateur ne se soucie pas de l'en-tête, seulement l'éditeur de liens.
La
extern "C"
autour de la définition n'est pas nécessaire. Vous pouvez vous en sortir avec juste de le mettre autour de la déclaration. Une note dans votre exemple...Votre code est à la recherche pour le préprocesseur macro "
__cplusplus
".Alors qu'il est couramment mis en œuvre, en fonction de votre compilateur, ce qui peut ou ne peut pas être définie. Dans votre exemple, vous utilisez également
extern "C"
autour de la déclaration, mais là, vous ne sont pas la vérification de la "__cplusplus
" macro c'est pourquoi je soupçonne que cela a fonctionné une fois que vous l'avez fait.Voir les commentaires ci-dessous Standard de C++ requiert l'
__cplusplus
macro définie par le préprocesseur.__cplusplus
" macro est requise par la norme à définir lors de la compilation d'un module C++ - il n'y a absolument pas de problèmes à l'utiliser.__cplusplus
" est souvent nécessaire dans les en-têtes (étant donné qu'ils peuvent être inclus en C ou C++ modules), il n'est généralement pas nécessaire .c ou .fichiers cpp, car ils sont généralement conçus pour être compilé comme le C ou le C++, mais pas les deux (il y a bien sûr des exceptions, mais généralement pas).Il devrait être d'environ deux à la fois. Le compilateur a besoin de savoir pour utiliser le nom de symbole C et de conventions d'appel lors de la compilation des sites d'appel (qui peuvent n'y voir qu'une déclaration), et le compilateur doit également savoir pour générer le nom de symbole C et du C conventions d'appel lors de la compilation de la définition de la fonction elle-même (qui peut ne pas voir les autres déclarations).
Maintenant, si vous avez une extern-C de la déclaration qui est visible à partir de la traduction de l'unité dans laquelle la définition existe, vous pourriez être en mesure de s'en tirer avec laissant le extern-C de la définition, mais je ne sais pas pour sûr.