2016-04-13 1 views
1

J'utilise mingw-w64 sous Windows 7 Pro 64 bits. En essayant d'accéder à des variables externes, après la déchirure beaucoup de cheveux, je suis finalement arrivé à ceci:Accès à une variable externe "C" en C++ à partir d'un autre fichier

// MultiTest2.h 
// Version 1.0.0 
// MDJ 2016/04/13 

#ifndef MULTITEST2_H 
#define MULTITEST2_H 

extern "C" { 
    int iXfer; 
    int setInt(); 
} 

#endif // MULTITEST2_H 

ne fonctionne pas (j'utilise « extern « C » » au lieu de simplement « extern » parce que je travaille vers la liaison au code d'assemblage éventuellement), mais:

// MultiTest2.h 
// Version 1.0.1 
// MDJ 2016/04/13 

#ifndef MULTITEST2_H 
#define MULTITEST2_H 

extern "C" int iXfer; 
extern "C" int setInt(); 

#endif // MULTITEST2_H 

Fonctionne!

Pour votre information, les deux autres fichiers du système sont les suivants:

// MultiTest2.cpp 
// Version 1.0.0 
// MDJ 2016/04/13 

#include "MultiTest2.h" 

int iXfer = 0; 

int setInt() { 
    iXfer = 6253; 
    return 0; 
} 

et:

// MultiTest1.cpp 
// Version 1.0.0 
// MDJ 2016/04/13 

#include <iostream> 
#include "MultiTest2.h" 

using namespace std; 

int main() { 
    setInt(); 
    cout << iXfer << endl; 
} 

Avec la version 1.0.0 de MultiTest2.h (les déclarations dans un « extern "C" «bloc), immédiatement après l'entrée:

g++ -S MultiTest2.cpp 

le résultat est:

MultiTest2.cpp:7:5: error: redefinition of 'int iXfer' 
int iXfer = 0; 
    ^
In file included from MultiTest2.cpp:5:0: 
MultiTest2.h:12:6: note: 'int iXfer' previously declared here 
    int iXfer; 
    ^

Mais, avec la version 1.0.1 de MultiTest2.h (individuel 'extern "C"' déclarations), la séquence suivante fonctionne parfaitement:

c:\work\gccWork\MultiTest>g++ -S MultiTest2.cpp 
c:\work\gccWork\MultiTest>g++ -S MultiTest1.cpp 
c:\work\gccWork\MultiTest>g++ -c MultiTest2.s 
c:\work\gccWork\MultiTest>g++ -c MultiTest1.s 
c:\work\gccWork\MultiTest>g++ -o MultiTest.exe MultiTest2.o MultiTest1.o 
c:\work\gccWork\MultiTest>MultiTest 
6253 

Est-ce une sorte de idiosyncrasie MinGW-w64, ou y a-t-il quelque chose qui me manque ici?

Répondre

0

Ce ne sont pas les mêmes.

extern "C" int foo; 

fait deux choses: il déclare que foo est extern (ie ceci est une déclaration que, et le symbole sera défini par un autre module), et elle démontre la liaison de foo comme « C », qui influence le nom du symbole.

D'autre part,

extern "C" { 
    int foo; 
} 

déclare seulement que foo a la liaison C. Il ne déclare pas le symbole comme extern, ce qui signifie qu'il s'agit d'une définition, pas seulement d'une déclaration.

En d'autres termes

extern "C" int foo; 

est le même que (notez la répétition du mot-clé extern)

extern "C" { 
    extern int foo; 
} 
+1

"Il ne fait pas le symbole ... extern" est pas exact. Les objets non-const déclarés dans la portée de l'espace de noms ont un lien externe par défaut. Il n'y a pas besoin de "les faire extern" de toute façon. Ce que 'extern' C "' ne fait pas dans ce cas, c'est qu'il ne transforme pas une * définition * en une * déclaration non-définissante * (comme le fait tout simplement 'extern'). – AnT

+0

@AnT merci, j'ai mis à jour le libellé. – AaronI