40 votes

Que signifie pour un nom ou un type un certain couplage linguistique?

Selon (c) ANSI ISO/IEC 14882:2003, page 127:

Lien spécifications du nid. Lorsque le couplage spécifications du nid, le plus intime de l'un détermine la langue. Un lien spécification ne permet pas d'établir une portée. Un lien-cahier des charges doivent se produire que dans l'espace de noms de la portée (3.3). Un lien-spécification, la langue spécifiée de liaison s'applique à la fonction des types de l'ensemble de la fonction declarators, les noms de fonction, et les noms de variables introduites par la déclaration(s).

extern "C" void f1(void(*pf)(int));
// the name f1 and its function type have C language
// linkage; pf is a pointer to a C function

extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage

extern "C" FUNC f3;
// the name of function f3 and the function's type
// have C language linkage

void (*pf2)(FUNC*);
// the name of the variable pf2 has C++ linkage and
// the type of pf2 is pointer to C++ function that
// takes one parameter of type pointer to C function

Que signifie tout cela? Par exemple, ce lien ne l' f2() de la fonction, langage C ou C++ liaison?

Comme l'a souligné @Johannes Schaub, il n'y a pas de véritable explication de ce que cela signifie dans la Norme, alors il peut être interprété différemment selon les compilateurs.

Veuillez expliquer les différences dans le fichier d'objet:

  • un nom de la fonction, avec le langage C de liaison et de langage C++ liaison.
  • une fonction du type de langage C de liaison et de langage C++ liaison.

16voto

Vikram.exe Points 2602

Langue de liaison est le terme utilisé pour la liaison entre C++ et non-C++ des fragments de code. Généralement, dans un programme C++, tous les noms de fonctions, des types de fonction et même les noms de variables ont le défaut de langage C++ liaison.

Un objet C++ code peut être lié à un autre code objet qui est produit en utilisant une autre langue ( C) à l'aide d'un prédéfini spécificateur de liaison.

Que vous devez être conscient de la notion de name mangling, qui code pour les noms de fonction, la fonction, les types et les noms de variables, de manière à générer un nom unique pour eux. Cela permet à l'éditeur de liens pour différencier les noms communs (comme dans le cas de la surcharge de fonction). Nom de déformation n'est pas souhaitable lors de la liaison des modules en C avec les bibliothèques ou les fichiers objet compilé avec un compilateur C++. Pour prévenir l'amputation des noms pour de tels cas, le lien avec les prescripteurs sont utilisés. Dans ce cas, extern "C" est le spécificateur de liaison. Prenons un exemple (code c++ mentionné ici):

typedef int (*pfun)(int);  // line 1
extern "C" void foo(pfun); // line 2
extern "C" int g(int)      // line 3
...
foo( g ); // Error!        // line 5

Ligne 1 déclare pfun pour pointer vers une fonction C++, car il lui manque un spécificateur de liaison.

Ligne 2 déclare toto à être une fonction C qui prend un pointeur vers une fonction C++.

Ligne 5 tente d'appeler foo avec un pointeur vers g, une fonction C, un type mis-match.

Diff dans le nom de la fonction de liaison:

Prenons deux fichiers différents:

Un avec extern "c" de la liaison (file1.cpp):

#include <iostream>
using namespace std;

extern "C"
{
void foo (int a, int b)
{
    cout << "here";
}
}

int main ()
{
    foo (10,20);
    return 0;
}

L'un sans l' extern "c" de la liaison (file2.cpp):

#include <iostream>
using namespace std;

void foo (int a, int b)
{
    cout << "here";
}

int main ()
{
    foo (10,20);
    return 0;
}

Maintenant compiler ces deux et de vérifier la objdump.

# g++ file1.cpp -o file1
# objdump -Dx file1

# g++ file2.cpp -o file2
# objdump -Dx file2

Avec liaison extern "C", il n'y a pas de nom d'amputation pour la fonction foo. Ainsi, tout programme qui l'utilise (en supposant que nous faire partagé lib hors de lui) peut directement appeler foo (avec des fonctions d'assistance comme dlsym et dlopen) avec de l'examen de toute amputation des noms des effets.

0000000000400774 <foo>:
  400774:   55                      push   %rbp
  400775:   48 89 e5                mov    %rsp,%rbp
....
....
  400791:   c9                      leaveq 
  400792:   c3                      retq   

0000000000400793 <main>:
  400793:   55                      push   %rbp
  400794:   48 89 e5                mov    %rsp,%rbp
  400797:   be 14 00 00 00          mov    $0x14,%esi
  40079c:   bf 0a 00 00 00          mov    $0xa,%edi
  4007a1:   e8 ce ff ff ff          callq  400774 <foo>
  4007a6:   b8 00 00 00 00          mov    $0x0,%eax
  4007ab:   c9                      leaveq 

D'autre part, lorsqu'il n' extern "C" est utilisé, func: foo est mutilé avec des règles prédéfinies (connu du compilateur/linker utilisé) et donc une application ne peut pas appeler directement à partir en spécifiant le nom qu' foo. Vous pouvez cependant appeler avec le nom décomposé (_Z3fooii dans ce cas), si vous voulez, mais personne ne l'utiliser, pour la raison évidente.

0000000000400774 <_Z3fooii>:
  400774:   55                      push   %rbp
  400775:   48 89 e5                mov    %rsp,%rbp
 ...
...
  400791:   c9                      leaveq 
  400792:   c3                      retq   

0000000000400793 <main>:
  400793:   55                      push   %rbp
  400794:   48 89 e5                mov    %rsp,%rbp
  400797:   be 14 00 00 00          mov    $0x14,%esi
  40079c:   bf 0a 00 00 00          mov    $0xa,%edi
  4007a1:   e8 ce ff ff ff          callq  400774 <_Z3fooii>
  4007a6:   b8 00 00 00 00          mov    $0x0,%eax
  4007ab:   c9                      leaveq 
  4007ac:   c3                      retq   

Cette page est aussi une bonne lecture pour ce sujet en particulier.

Une belle et clairement expliqué article sur la convention d'appel: http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx

2voto

Roee Gavirel Points 4550

"le nom de f2 a langage C++ lien" En langage C++ liaison non seulement le nom de la fonction qui définit, mais aussi le type des arguments et de la valeur de retour. dans ce cas, vous devez: void f2(void); mais vous pouvez définir avec elle: void f2(int a); sans conflit, car le couplage permettra de les voir comme des types différents, une chose que vous ne serait pas en mesure de le faire en langage C.

"la fonction du type a C langue de liaison" Je ne connais pas les détails, mais je sais que l'informatique de haut niveau. Fondamentalement, il fait une C++ compilé fonction réticulable de C. Si je me souviens bien en C et En C++ la façon dont les paramètres sont passés à une fonction différente. Dans ce cas, la fonction f2 passer les paramètres comme le compilateur C ne de cette. de cette façon, la fonction va être couplés à la fois à partir de C et de C++.

2voto

Bo Persson Points 42821
 extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage
 

Le nom FUNC est déclaré avec une liaison "C" car il indique extern "C" sur la première ligne.

Le nom f2 a une liaison C ++ car il s'agit de la valeur par défaut et aucune autre liaison n'est donnée à la ligne deux.

Le fait que le nom f2 soit utilisé pour faire référence à une fonction avec une liaison C ne modifie pas la liaison du nom .

2voto

Mehrdad Points 70493

Il a à voir avec l' ABI (Application Binary Interface) du programme.

Comme une API spécifie l'interface externe du code source d'un programme, d'un ABI spécifie l'interface externe du code binaire du programme (la version compilée).


À l'origine, les fonctions C tout simplement eu un peu de formes différentes. Quelque chose comme

int foo(int);

serait précédé par un trait de soulignement par le compilateur, pour former _foo, puis exportées pour être mis à la disposition d'autres applications.

Cependant, ce n'était pas assez. Si vous regardez l'API de Windows, par exemple, vous verrez des choses comme:

DWORD CreateWindowW(...);        //Original parameters
DWORD CreateWindowExW(..., ...); //More parameters

C'est parce qu'il n'y a aucun moyen de distinguer entre les surcharges d'une fonction simplement en regardant le nom de la fonction, de sorte que les gens ont commencé à les modifier par l'ajout d'un Ex suffixe (ou similaire).

Ce a grandi pour être assez laid, et il n'a pas encore de permettre la surcharge d'opérateur, qui a été présenté en C++. De ce fait, le C++ est venu avec name mangling, de mettre des informations supplémentaires dans le nom de la fonction, comme les types de données de ses paramètres, et d'en faire quelque chose d'énigmatique avec beaucoup d' @ symboles.

Tout était bien, sauf que ce n'est pas complètement normalisée.

Bien sûr, comme de nouveaux langages et compilateurs venu à propos, chacun est venu avec son propre système, incompatible avec les autres. Donc, si vous avez besoin d'importer ou d'exporter une fonction externe, vous devez spécifier quel type de ABI le compilateur doit chercher, d'où l' extern "C++" que vous avez là.

2voto

Tony D Points 43962

Que signifie tout cela? Par exemple, ce lien ne la touche f2() de la fonction, langage C ou C++ liaison?

extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the 
// function's type has C language linkage 

Ce que vous appelez le "f2() la fonction" a deux aspects de son lien:

  • les mutilations ou pas de son nom dans la table des symboles (qui a langage C++ de liaison), et
  • le C ou C++ convention d'appel nécessaire si la fonction appelée (C).

Pour appeler f2() vous trouvez son nom aka symbole dans le fichier de l'objet, qui sera un mutilé de la version de "fonction nommée f2 prenant pas d'argument". Vous pouvez le vérifier trivialement en compilant le code ci-dessus et l'inspection de l'objet (par exemple w/ outils GNU nm --demangle).

Mais pour appeler la fonction, les conventions pour les pré - et post-conditions de registre d'utilisation, la pile de configuration etc. sont ceux d'un C fonctions. Il est légal pour le C et le C++ fonctions différentes conventions d'appel, et peut-être fait - par exemple - afin de faciliter la gestion des exceptions C++.

Veuillez expliquer les différences dans le fichier d'objet: un nom de la fonction, avec le langage C de liaison et de langage C++ liaison.

  • pour une liaison C, "f2" serait le symbole dans le fichier de l'objet résultant de l' f2()
  • pour le C++ liaison, certains mutilés version de "fonction nommée f2 prenant pas d'arguments" (pour GNU, _Z2f2v qui demangles d' f2())

une fonction du type de langage C de liaison et de langage C++ liaison.

Comme discuté ci-dessus, c'est sur le registre du/de la pile utilisation de la convention pour appeler le code à l'adresse de la fonction. Cette méta-information n'est pas nécessairement stockées dans la table des symboles d'information de l'objet (et certainement ne fait pas partie du nom du symbole de la clé elle-même).

En outre, parce que chaque fonction adopte l'une des conventions d'appel, un compilateur a besoin de savoir la convention d'appel à utiliser lorsque à la suite d'un pointeur à une fonction: avec cette idée, je pense que le reste du code dans la question devient clair.

Il y a une excellente discussion à http://developers.sun.com/solaris/articles/mixing.html - en particulier, je recommande la section Travailler avec des Pointeurs de Fonctions.

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