quoi - visual c++ extern variable




Quel est l'effet de extern "C" en C++? (8)

C ++ altère les noms de fonction pour créer un langage orienté objet à partir d'un langage procédural

La plupart des langages de programmation ne sont pas construits sur les langages de programmation existants. C ++ est construit au dessus de C, et de plus c'est un langage de programmation orienté objet construit à partir d'un langage de programmation procédural, et pour cette raison il y a des mots-clés C ++ comme extern qui offrent une compatibilité ascendante avec C.

Regardons l'exemple suivant:

#include <stdio.h>

// Two functions are defined with the same name
// but have different parameters

void printMe(int a) {
  printf("int: %i\n", a);
}

void printMe(char a) {
  printf("char: %c\n", a);
}

int main() {
  printMe("a");
  printMe(1);
  return 0;
}

Le compilateur AC ne compilera pas l'exemple ci-dessus, parce que la même fonction printMe est définie deux fois (même si elle a des paramètres différents en int a vs char a ).

gcc -o printMe printMe.c && ./printMe;
1 erreur. PrintMe est défini plusieurs fois.

Un compilateur C ++ compilera l'exemple ci-dessus. Cela ne fait rien que printMe soit défini deux fois.

g ++ -o printMe printMe.c && ./printMe;

En effet, un compilateur C ++ renomme implicitement les fonctions ( en.wikipedia.org/wiki/Name_mangling ) en fonction de leurs paramètres. En C, cette fonctionnalité n'était pas supportée. Cependant, lorsque C ++ était construit sur C, le langage était conçu pour être orienté objet, et devait supporter la possibilité de créer différentes classes avec des méthodes (fonctions) du même nom, et de surcharger des méthodes (surchargement de méthodes) basées sur différents paramètres.

Extern dit "ne pas manchonner les noms de fonction"

Cependant, imaginons que nous ayons un fichier C hérité nommé "parent.c" qui include les noms de fonctions s d'autres fichiers C hérités, "parent.h", "child.h", etc. Si le fichier hérité "parent.c" est exécuter un compilateur C ++, les noms des fonctions seront tronqués, et ils ne correspondront plus aux noms de fonctions spécifiés dans "parent.h", "child.h", etc - donc les noms de fonctions dans ces fichiers externes devraient être mutilé aussi bien. Et cela pourrait devenir assez salissant. Il peut donc être pratique de fournir un mot-clé qui peut indiquer au compilateur C ++ de ne pas manipuler un nom de fonction.

Le mot-clé extern indique à un compilateur C ++ de ne pas renommer les noms de fonction. Exemple d'utilisation: extern void printMe(int a);

Qu'est-ce que faire d' extern "C" dans le code C ++?

Par exemple:

extern "C" {
   void foo();
}

Aucun C-header ne compilera avec extern "C". Lorsque les identifiants d'un en-tête C entrent en conflit avec des mots-clés C ++, le compilateur C ++ s'en plaindra.

Par exemple, j'ai vu le code suivant échouer dans un g ++:

extern "C" {
struct method {
    int virtual;
};
}

Kinda a du sens, mais c'est quelque chose à garder à l'esprit lors du portage du code C en C ++.


Il informe le compilateur C ++ de rechercher les noms de ces fonctions dans un style C lors de la liaison, car les noms des fonctions compilées en C et C ++ sont différents au cours de la phase de liaison.


Il modifie le lien d'une fonction de telle sorte que la fonction soit appelable à partir de C. En pratique, cela signifie que le nom de la fonction n'est pas mangled .


Je voulais juste ajouter un peu d'info, car je ne l'ai pas encore vu.

Vous verrez très souvent du code dans les en-têtes C comme ceci:

#ifdef __cplusplus
extern "C" {
#endif

// all of your legacy C code here

#ifdef __cplusplus
}
#endif

Ce que cela permet, c'est qu'il vous permet d'utiliser ce fichier d'en-tête C avec votre code C ++, car la macro "__cplusplus" sera définie. Mais vous pouvez toujours l'utiliser avec votre code C hérité, où la macro n'est pas définie, donc il ne verra pas la construction C ++ unique.

Bien que, j'ai également vu le code C ++ tel que:

extern "C" {
#include "legacy_C_header.h"
}

ce que j'imagine accomplit à peu près la même chose.

Je ne sais pas quel est le meilleur, mais j'ai vu les deux.


Lors du mélange de C et C ++ (c'est-à-dire, une fonction C appelant de C ++ et b) l'appel de la fonction C ++ de C), le changement de nom C ++ provoque des problèmes de liaison. Techniquement parlant, ce problème se produit uniquement lorsque les fonctions de l'appelé ont déjà été compilées en binaire (très probablement, un fichier de bibliothèque * .a) en utilisant le compilateur correspondant.

Nous devons donc utiliser extern "C" pour désactiver le nom mangling en C ++.


extern "C" fait un nom de fonction en C ++ avec un lien 'C' (le compilateur ne déforme pas le nom) afin que le code C client puisse lier (c'est-à-dire utiliser) votre fonction en utilisant un fichier d'en-tête compatible 'C' déclaration de votre fonction. Votre définition de fonction est contenue dans un format binaire (qui a été compilé par votre compilateur C ++) que l'éditeur de liens client 'C' liera alors en utilisant le nom 'C'.

Comme le C ++ est surchargé de noms de fonctions et que C ne le fait pas, le compilateur C ++ ne peut pas simplement utiliser le nom de la fonction en tant qu'ID unique pour lier, donc il altère le nom en ajoutant des informations sur les arguments. Le compilateur AC n'a pas besoin d'altérer le nom puisque vous ne pouvez pas surcharger les noms de fonction en C. Lorsque vous déclarez qu'une fonction a un lien externe "C" en C ++, le compilateur C ++ n'ajoute pas d'informations argument / type au nom utilisé lien.

Juste pour que vous sachiez, vous pouvez spécifier explicitement le lien "C" à chaque déclaration / définition individuelle ou utiliser un bloc pour grouper une séquence de déclarations / définitions afin d'avoir un certain lien:

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}

Si vous vous souciez des détails techniques, ils sont listés dans la section 7.5 de la norme C ++ 03, voici un bref résumé (en mettant l'accent sur extern "C"):

  • extern "C" est une spécification de liaison
  • Chaque compilateur doit fournir une liaison "C"
  • une spécification de liaison doit se produire uniquement dans l'étendue de l'espace de noms
  • tous les types de fonctions, les noms de fonctions et les noms de variables ont un lien de langage Voir le commentaire de Richard: Seuls les noms de fonctions et les noms de variables avec un lien externe ont un lien de langage
  • deux types de fonctions avec des liens linguistiques distincts sont des types distincts même s'ils sont identiques
  • Nid spécification de liaison, l'interne détermine la liaison finale
  • extern "C" est ignoré pour les membres de la classe
  • au plus une fonction avec un nom particulier peut avoir un lien "C" (indépendamment de l'espace de noms)
  • extern "C" force une fonction à avoir un lien externe (ne peut pas le rendre statique) Voir le commentaire de Richard: 'static' dans 'extern' C "'est valide; une entité ainsi déclarée a un lien interne, et n'a donc pas de lien de langage
  • La liaison de C ++ à des objets définis dans d'autres langages et à des objets définis en C ++ à partir d'autres langages est définie par l'implémentation et dépend de la langue. Ce n'est que lorsque les stratégies de mise en page d'objets de deux implémentations de langage sont suffisamment similaires que ce lien peut être atteint

extern "C" est une spécification de liaison qui est utilisée pour appeler les fonctions C dans les fichiers source Cpp . Nous pouvons appeler des fonctions C, écrire des variables et inclure des en-têtes . La fonction est déclarée dans l'entité externe et elle est définie à l'extérieur. La syntaxe est

Type 1:

extern "language" function-prototype

Type 2:

extern "language"
{
     function-prototype
};

par exemple:

#include<iostream>
using namespace std;

extern "C"
{
     #include<stdio.h>    // Include C Header
     int n;               // Declare a Variable
     void func(int,int);  // Declare a function (function prototype)
}

int main()
{
    func(int a, int b);   // Calling function . . .
    return 0;
}

// Function definition . . .
void func(int m, int n)
{
    //
    //
}






extern-c