Lorsque j'essaie de construire un programme en utilisant Eclipse CDT
J'obtiens ce qui suit :
/mingw/lib/libmingw32.a(main.o):main.c :(.text+0x106) : référence indéfinie à `WinMain@16
Pourquoi ? Et, comment puis-je résoudre ce problème ?
Lorsque j'essaie de construire un programme en utilisant Eclipse CDT
J'obtiens ce qui suit :
/mingw/lib/libmingw32.a(main.o):main.c :(.text+0x106) : référence indéfinie à `WinMain@16
Pourquoi ? Et, comment puis-je résoudre ce problème ?
Cette erreur se produit lorsque l'éditeur de liens ne peut trouver WinMain
donc elle est probablement manquante. Dans votre cas, il vous manque probablement main
aussi.
Considérez le programme de niveau API Windows suivant :
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Maintenant, construisons-le en utilisant la chaîne d'outils GNU (i.e. g++), sans options spéciales. Voici gnuc
est juste un fichier batch que j'utilise pour ça. Il fournit seulement des options pour rendre g++ plus standard :
C:\\test> gnuc x.cpp
C:\\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000003 (Windows CUI)
C:\\test> \_
Cela signifie que l'éditeur de liens a produit par défaut un fichier sous-système de la console exécutable. Le site sous-système dans l'en-tête du fichier indique à Windows les services requis par le programme. Dans ce cas, avec le système console, que le programme nécessite une fenêtre console.
L'interpréteur de commandes attend alors que le programme se termine.
Maintenant, nous allons le construire avec Sous-système GUI ce qui signifie simplement que le programme n'a pas besoin d'une fenêtre de console :
C:\\test> gnuc x.cpp -mwindows
C:\\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\\test> \_
J'espère que c'est bon jusqu'à présent, bien que la -mwindows
est juste semi-documenté.
En construisant sans ce drapeau semi-documenté, il faudrait indiquer plus spécifiquement à l'éditeur de liens quelle valeur de sous-système on souhaite, 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 "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\\test> \_
Cela a bien fonctionné, avec la chaîne d'outils GNU.
Mais qu'en est-il de la chaîne d'outils de Microsoft, c'est-à-dire Visual C++ ?
Eh bien, la construction en tant qu'exécutable du sous-système de la console fonctionne bien :
C:\\test> msvc x.cpp user32.lib
x.cpp
C:\\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
3 subsystem (Windows CUI)
C:\\test> \_
Cependant, avec la chaîne d'outils de Microsoft, la construction d'un sous-système GUI ne fonctionne pas par défaut :
C:\\test> msvc x.cpp user32.lib /link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol \_WinMain@16 referenced in function \_\_\_tmainCRTStartu
p
x.exe : fatal error LNK1120: 1 unresolved externals
C:\\test> \_
Techniquement, c'est parce que l'éditeur de liens de Microsoft est non standard par défaut pour le sous-système GUI . Par défaut, lorsque le sous-système est une interface graphique, l'éditeur de liens de Microsoft utilise une bibliothèque d'exécution. point d'entrée la fonction où l'exécution du code machine commence, appelée winMainCRTStartup
qui appelle le système non standard de Microsoft WinMain
au lieu de la norme main
.
Ce n'est pas un problème de réparer ça, cependant.
Tout ce que vous avez à faire est d'indiquer à l'éditeur de liens de Microsoft le point d'entrée à utiliser, à savoir mainCRTStartup
qui appelle la norme main
:
C:\\test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup
x.cpp
C:\\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
2 subsystem (Windows GUI)
C:\\test> \_
Pas de problème, mais très fastidieux. Et tellement obscure et cachée que la plupart des programmeurs Windows, qui n'utilisent pour la plupart que les outils non standard par défaut de Microsoft, ne le savent même pas, et pensent à tort qu'un programme du sous-système d'interface graphique Windows "doit" avoir des outils non standard. WinMain
au lieu de la norme main
. En passant, avec C++0x, Microsoft aura un problème avec cela, puisque le compilateur doit alors annoncer s'il est autonome ou hébergé (lorsqu'il est hébergé, il doit supporter le standard main
).
Quoi qu'il en soit, c'est la raison pour laquelle g++ puede se plaindre de WinMain
manquant : il s'agit d'une fonction de démarrage stupide et non standard que les outils de Microsoft exigent par défaut pour les programmes du sous-système GUI.
Mais comme vous pouvez le voir ci-dessus, g++ n'a aucun problème avec le standard main
même pour un programme de sous-système GUI.
Alors quel pourrait être le problème ?
Eh bien, vous êtes probablement manquant a main
. Et vous n'avez probablement pas (correctement) WinMain
soit ! Et puis g++, après avoir cherché main
(qui n'existe pas), et pour le système non standard de Microsoft WinMain
(pas de 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 to \`WinMain@16'
collect2: ld returned 1 exit status
C:\\test> \_
Alf P. Steinbach. Merci beaucoup pour votre belle réponse. En ce qui concerne All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. Y a-t-il un moyen de le faire Eclipse CDT
car je n'utilise pas la ligne de commande. Merci
@user588855 : puisque vous utilisez g++, cela ne s'applique (probablement) pas à vous. Seule la partie à la fin s'applique (probablement). C'est-à-dire, définissez un main
ou un WinMain
ou assurez-vous que le fichier correspondant est inclus dans le projet. A la vôtre,
Je viens de réaliser quelque chose d'important à propos de tout ça. Dans mon cas, il ne trouvait pas main() car je n'avais pas déclaré d'arguments (argc, argv). Une fois ajouté, il a trouvé main. Aussi, la nature de la façon dont cela fonctionne signifie que mingw essaie d'aider en fournissant son propre main qui à son tour appelle WinMain. Les programmes GUI n'auraient que WinMain et le stub main de mingw est utilisé pour y arriver. Si vous avez un main, alors il l'utilise à la place.
Merci beaucoup ! Cette commande fonctionne : gcc main.c -I " E:\Libs\SDL2 -devel-2.0.12-mingw \SDL2 -2.0.12 \i686 -w64-mingw32 \include " -I" E:\Libs\SDL2_ttf -devel-2.0.15-mingw \SDL2_ttf -2.0.15 \i686 -w64-mingw32 \include " -L" E:\Libs\SDL2 -devel-2.0.12-mingw \SDL2 -2.0.12 \i686 -w64-mingw32 \lib " -L" E:\Libs\SDL2_ttf -devel-2.0.15-mingw \SDL2_ttf -2.0.15 \i686 -w64-mingw32 \lib " -lSDL2 -lSDL2main -lSDL2_ttf -o app.exe
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.
2 votes
Essayez de sauvegarder votre fichier et de le ré-exécuter dans mon cas, cela a fonctionné.