Référence indéfinie à `WinMain @ 16 ‘

Lorsque j’essaie de créer un programme en utilisant Eclipse CDT , j’obtiens les éléments suivants:

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): référence indéfinie à `WinMain @ 16

Pourquoi donc? Et comment résoudre ce problème?

Considérons le programme suivant au niveau de l’API Windows:

 #define NOMINMAX #include  int main() { MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND ); } 

Maintenant, construisons-le en utilisant la chaîne d’outils GNU (c’est-à-dire g ++), sans options spéciales. Ici, gnuc est juste un fichier batch que j’utilise pour cela. Il ne fournit que des options pour rendre g ++ plus standard:

 C: \ test> gnuc x.cpp

 C: \ test> objdump -x a.exe |  findstr / i "^ sous-système"
 Sous-système 00000003 (Windows CUI)

 C: \ test> _

Cela signifie que l’éditeur de liens produit par défaut un exécutable de sous-système de console . La valeur du sous-système dans l’en-tête du fichier indique à Windows les services requirejs par le programme. Dans ce cas, avec le système de console, le programme nécessite une fenêtre de console.

Cela entraîne également l’interpréteur de commandes à attendre que le programme se termine.

Maintenant, construisons-le avec le soussystème GUI , ce qui signifie simplement que le programme ne nécessite pas de fenêtre de console:

 C: \ test> gnuc x.cpp -mwindows

 C: \ test> objdump -x a.exe |  findstr / i "^ sous-système"
 Sous-système 00000002 (interface graphique Windows)

 C: \ test> _

J’espère que tout va bien pour l’instant, bien que le drapeau -mwindows ne soit que -mwindows documenté.

En l’absence de cet indicateur semi-documenté, il faudrait indiquer plus précisément à l’éditeur de liens la valeur de sous-système souhaitée, et certaines bibliothèques d’importation de l’API Windows devront alors être spécifiées explicitement:

 C: \ test> gnuc x.cpp -Wl, -subsystem, windows

 C: \ test> objdump -x a.exe |  findstr / i "^ sous-système"
 Sous-système 00000002 (interface graphique Windows)

 C: \ test> _

Cela a bien fonctionné, avec la chaîne d’outils GNU.

Mais qu’en est-il de la chaîne d’outils Microsoft, à savoir Visual C ++?

Eh bien, la construction en tant que sous-système de console exécutable fonctionne bien:

 C: \ test> msvc x.cpp user32.lib
 x.cpp

 C: \ test> dumpbin / headers x.exe |  trouver / i "sous-système" |  trouver / i "Windows"
                3 sous-systèmes (Windows CUI)

 C: \ test> _

Toutefois, avec la création de chaînes d’outils Microsoft, le sous-système d’interface graphique ne fonctionne pas par défaut:

 C: \ test> msvc x.cpp user32.lib / link / sous-système: windows
 x.cpp
 LIBCMT.lib (wincrt0.obj): erreur LNK2019: symbole externe non résolu _WinMain @ 16 référencé dans la fonction ___tmainCRTStartu
 p
 x.exe: erreur fatale LNK1120: 1 externes non résolus

 C: \ test> _

Techniquement, c’est parce que l’éditeur de liens de Microsoft n’est pas standard par défaut pour le sous-système de l’interface graphique . Par défaut, lorsque le sous-système est une interface graphique, l’éditeur de liens de Microsoft utilise un point d’entrée de bibliothèque d’exécution, la fonction d’exécution du code machine appelée winMainCRTStartup , qui appelle WinMain non standard WinMain lieu du standard.

Pas de gros problème pour régler cela, cependant.

Tout ce que vous avez à faire est de dire à l’éditeur de liens de Microsoft quel point d’entrée utiliser, à savoir mainCRTStartup , qui appelle la main :

 C: \ test> msvc x.cpp user32.lib / link / sous-système: windows / entry: mainCRTStartup
 x.cpp

 C: \ test> dumpbin / headers x.exe |  trouver / i "sous-système" |  trouver / i "Windows"
                2 sous-systèmes (Windows GUI)

 C: \ test> _

Pas de problème, mais très fastidieux. Et si obscure et cachée que la plupart des programmeurs Windows, qui utilisent principalement les outils non standard par défaut de Microsoft, ne le savent même pas, et pensent à tort qu’un programme de sous-système graphique Windows «doit» avoir WinMain non standard WinMain lieu de main standard. En passant, avec C ++ 0x, Microsoft aura un problème avec cela, car le compilateur doit ensuite annoncer s’il est autonome ou hébergé (lorsqu’il est hébergé, il doit prendre en charge le main standard).

Quoi qu’il en soit, c’est la raison pour laquelle g ++ peut se plaindre de l’ WinMain de WinMain : c’est une fonction de démarrage non standard stupide que les outils de Microsoft requièrent par défaut pour les programmes de sous-systèmes à interface graphique.

Mais comme vous pouvez le voir ci-dessus, g ++ n’a pas de problème avec la version standard même pour un programme de sous-système graphique.

Alors, quel pourrait être le problème?

Eh bien, vous manquez probablement une main . Et vous n’avez probablement pas WinMain plus WinMain ! Et puis g ++, après avoir recherché le main (pas un tel), et pour WinMain non standard de WinMain (non tel), signale que ce dernier est manquant.

Test avec une source vide:

 C: \ test> type nul> y.cpp

 C: \ test> gnuc y.cpp -mwindows
 c: / program files / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. text + 0xd2 ): undefined referen
 ce à `WinMain @ 16 '
 collect2: ld a renvoyé 1 état de sortie

 C: \ test> _

Pour résumer le message ci-dessus par Cheers et hth. – Alf, assurez-vous que main() ou WinMain() définis et que g ++ devrait faire ce qui est bien.

Mon problème était que main() était défini par accident dans un espace de noms.

J’ai rencontré cette erreur lors de la compilation de mon application avec SDL. Cela était dû au fait que SDL définissait sa propre fonction principale dans SDL_main.h. Pour empêcher le SDL de définir la fonction principale, une macro SDL_MAIN_HANDLED doit être définie avant l’inclusion de l’en-tête SDL.h.

Essayez d’enregistrer votre fichier .c avant de le construire. Je crois que votre ordinateur fait référence à un chemin vers un fichier sans aucune information à l’intérieur.

– Problème similaire lors de la construction de projets C