Comment fonctionne une déclaration "c" externe?
je prends un cours de langues de programmation et nous parlons de la extern "C"
déclaration.
comment cette déclaration fonctionne-t-elle à un niveau plus profond que "it interfaces C et C++"? Comment cela affecte les liaisons qui ont lieu dans le programme?
9 réponses
extern "C"
est utilisé pour s'assurer que les symboles suivants ne sont pas mutilé (décoré).
Exemple:
disons que nous avons le code suivant dans un fichier appelé test.cpp
:
extern "C" {
int foo() {
return 1;
}
}
int bar() {
return 1;
}
si vous courez gcc -c test.cpp -o test.o
regardez les noms des symboles:
00000010 T _Z3barv
00000000 t foo
foo()
garde son nom.
regardons une fonction typique qui peut compiler en C et C++:
int Add (int a, int b)
{
return a+b;
}
Maintenant, en C la fonction est appelée "_Add" en interne. Tandis que la fonction C++ est appelée quelque chose de complètement différent à l'intérieur en utilisant un système appelé nom-mangling. C'est fondamentalement une façon de nommer une fonction de sorte que la même fonction avec des paramètres différents a un Nom interne différent.
donc si Add () est défini dans add.c, et vous avez le prototype en add.h, vous obtiendrez un problème si vous essayez d'inclure ajouter.h dans un fichier c++. Parce que le code C++ est à la recherche d'une fonction avec un nom différent de celui en ajouter.c vous obtiendrez une erreur de linker. Pour contourner ce problème, vous devez inclure ajouter.c par cette méthode:
extern "C"
{
#include "add.h"
}
maintenant le code C++ se liera avec _Add au lieu de la version de nom c++ mangée.
C'est l'une des utilisations de l'expression. En fin de compte, si vous avez besoin de compiler du code qui est strictement C dans un programme C++ (via un include déclaration ou un autre moyen) vous avez besoin de l'envelopper avec un "C" externe { ... } déclaration.
quand vous marquez un bloc de code avec un "C" externe, vous dites au système d'utiliser un lien de style C.
ceci, principalement, affecte la façon dont le linker coupe les noms. Au lieu d'utiliser le nom de style C++ mangling (qui est plus complexe pour supporter les surcharges d'opérateur), vous obtenez le nom de style C standard du linker.
en C++ le nom / symbole des fonctions est en fait renommé à quelque chose d'autre tel que différentes classes/namespaces peuvent avoir des fonctions de même signatures. Dans C, les fonctions sont toutes définies globalement et aucun processus de renommage personnalisé n'est nécessaire.
pour faire parler C++ et C l'un avec l'autre, "extern C" demande au compilateur de ne pas utiliser la convention C.
Il est à noter que extern "C"
modifie également les types de fonctions. Ce n'est pas seulement de modifier des choses sur les niveaux inférieurs:
extern "C" typedef void (*function_ptr_t)();
void foo();
int main() { function_ptr_t fptr = &foo; } // error!
le type de &foo
n'est pas égal au type que le typedef désigne (bien que le code soit accepté par certains, mais pas par tous les compilateurs).
extern C affecte la modification du nom par le compilateur C++. Son un moyen d'obtenir le compilateur C++ de ne pas coder les noms, ou plutôt à la mutilation de la même manière qu'un compilateur C. C'est la façon dont il se connecte C et C++.
comme exemple:
extern "C" void foo(int i);
permettra à la fonction d'être implémentée dans un module C, mais permettra qu'elle soit appelée à partir d'un module C++.
le problème vient quand on essaie d'obtenir un module C pour appeler une fonction c++ (évidemment C ne peut pas utilisez les classes c++) définies dans un module c++. Le compilateur C n'aime pas extern "C"
.
vous devez donc utiliser ceci:
#ifdef __cplusplus
extern "C" {
#endif
void foo(int i);
#ifdef __cplusplus
}
#endif
lorsque cela apparaît dans un fichier d'en-tête, les compilateurs C et c++ seront satisfaits de la déclaration et celle-ci peut désormais être définie dans un module C ou C++, et peut être appelée à la fois par le code C et c++.
extern "C" indique que le code ci-joint utilise la liaison de style C et la modification des noms. C++ utilise un format plus complexe pour la modification des noms. Voici un exemple:
http://en.wikipedia.org/wiki/Name_mangling
int example(int alpha, char beta);
EN C:_example
EN c++:__Z7exampleic
mise à jour: comme le note GManNickG dans les commentaires, le pattern de nom mangling est dépendant du compilateur.
extern "C", est un mot-clé pour déclarer une fonction avec des liaisons C, parce que le compilateur C et le compilateur C++ traduiront la source sous une forme différente dans le fichier objet:
Par exemple, un extrait de code est comme suit:
int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}
32 bits C compilateurs traduire le code dans le formulaire comme suit:
_func1
_func2@4
@func3@4
dans le cdecl, func1 se traduira par'_name'
dans le stdcall, func2 se traduit par ' _name@x'
dans le fastcall, func2 se traduira par'@nom@X'
' X " signifie le nombre d'octets de paramètres dans la liste des paramètres.
64 bits convention sur Windows n'a aucun trait de soulignement
en C++, Les classes, les gabarits, les namespaces et la surcharge de l'opérateur sont introduits, puisqu'il n'est pas permis deux fonctions avec le même nom, C++ compiler fournir l'information de type dans le symbole nom,
par exemple, un extrait de code est comme suit:
int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}
C++ compilateur traduit le code comme suit:
int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}
'_v' et '_i' sont des informations de type "void" et "int"
Voici une citation de msdn
" le mot clé externe déclare une variable ou une fonction et spécifie qu'elle a un lien externe (son nom est visible à partir de fichiers autres que celui dans lequel elle est définie). Lors de la modification d'une variable, extern spécifie que la variable a une durée statique (elle est affectée lorsque le programme commence et désallouée lorsque le programme se termine). La variable ou la fonction peut être définie dans un autre fichier source, ou plus tard dans le même fichier. Les déclarations de les variables et les fonctions à la portée du fichier sont externes par défaut."
http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx