Respuestas:
Considere el siguiente programa de nivel de API de Windows:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Ahora vamos a construirlo usando la cadena de herramientas GNU (es decir, g ++), sin opciones especiales. Aquí gnuc
hay solo un archivo por lotes que utilizo para eso. Solo proporciona opciones para hacer que g ++ sea más estándar:
C: \ prueba> gnuc x.cpp C: \ prueba> objdump -x a.exe | Findstr / i "^ subsistema" Subsistema 00000003 (CUI de Windows) C: \ prueba> _
Esto significa que el enlazador produjo de forma predeterminada un ejecutable del subsistema de consola . El valor del subsistema en el encabezado del archivo le dice a Windows qué servicios requiere el programa. En este caso, con sistema de consola, el programa requiere una ventana de consola.
Esto también hace que el intérprete de comandos espere a que se complete el programa.
Ahora construyémoslo con el subsistema GUI , lo que solo significa que el programa no requiere una ventana de consola:
C: \ prueba> gnuc x.cpp -mwindows C: \ prueba> objdump -x a.exe | Findstr / i "^ subsistema" Subsistema 00000002 (GUI de Windows) C: \ prueba> _
Con suerte, eso está bien hasta ahora, aunque la -mwindows
bandera está semidocumentada.
Construyendo sin esa bandera semidocumentada, uno tendría que decirle más específicamente al vinculador qué valor de subsistema se desea, y algunas bibliotecas de importación de API de Windows, en general, deberán especificarse explícitamente:
C: \ prueba> gnuc x.cpp -Wl, -subsystem, windows C: \ prueba> objdump -x a.exe | Findstr / i "^ subsistema" Subsistema 00000002 (GUI de Windows) C: \ prueba> _
Eso funcionó bien, con la cadena de herramientas GNU.
Pero, ¿qué pasa con la cadena de herramientas de Microsoft, es decir, Visual C ++?
Bueno, la construcción como un ejecutable de subsistema de consola funciona bien:
C: \ prueba> msvc x.cpp user32.lib x.cpp C: \ prueba> dumpbin / headers x.exe | buscar / i "subsistema" | buscar / i "Windows" 3 subsistema (CUI de Windows) C: \ prueba> _
Sin embargo, con la construcción de la cadena de herramientas de Microsoft como subsistema de GUI no funciona de forma predeterminada:
C: \ prueba> msvc x.cpp user32.lib / link / subsystem: windows x.cpp LIBCMT.lib (wincrt0.obj): error LNK2019: símbolo externo no resuelto _WinMain @ 16 referenciado en la función ___tmainCRTStartu pags x.exe: error fatal LNK1120: 1 externos sin resolver C: \ prueba> _
Técnicamente, esto se debe a que el enlazador de Microsoft no es estándar por defecto para el subsistema GUI . De forma predeterminada, cuando el subsistema es GUI, entonces el enlazador de Microsoft usa un punto de entrada de biblioteca en tiempo de ejecución , la función donde comienza la ejecución del código de máquina, llamada winMainCRTStartup
, que llama a Microsoft no estándar en WinMain
lugar de estándar main
.
Sin embargo, no es gran cosa arreglar eso.
Todo lo que tiene que hacer es decirle al vinculador de Microsoft qué punto de entrada usar, es decir mainCRTStartup
, cuál llama estándar main
:
C: \ prueba> msvc x.cpp user32.lib / link / subsystem: windows / entrada: mainCRTStartup x.cpp C: \ prueba> dumpbin / headers x.exe | buscar / i "subsistema" | buscar / i "Windows" 2 subsistema (GUI de Windows) C: \ prueba> _
No hay problema, pero muy tedioso. Y tan arcano y oculto que la mayoría de los programadores de Windows, que en su mayoría solo usan las herramientas no estándar por defecto de Microsoft, ni siquiera lo saben, y piensan erróneamente que un programa de subsistema de GUI de Windows "debe" tener un programa no estándar en WinMain
lugar de estándar. main
. De paso, con C ++ 0x Microsoft tendrá un problema con esto, ya que el compilador debe anunciar si es independiente o alojado (cuando está alojado debe ser compatible con el estándar main
).
De todos modos, esa es la razón por la que g ++ puede quejarse de la WinMain
falta: es una función de inicio tonta y no estándar que las herramientas de Microsoft requieren por defecto para los programas del subsistema GUI.
Pero como puede ver arriba, g ++ no tiene ningún problema con el estándar, main
incluso para un programa de subsistema GUI.
Entonces, ¿Cuál podría ser el problema?
Bueno, probablemente te falte un main
. ¡Y probablemente tampoco tengas (adecuado) WinMain
! Y luego g ++, después de haber buscado main
(no such), y de Microsoft no estándar WinMain
(no such), informa que falta este último.
Prueba con una fuente vacía:
C: \ prueba> escriba nul> y.cpp C: \ prueba> gnuc y.cpp -mwindows c: / archivos de programa / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. text + 0xd2 ): referencia indefinida ce a 'WinMain @ 16' collect2: ld devolvió 1 estado de salida C: \ prueba> _
main
o un WinMain
, o asegúrese de que el archivo relevante esté incluido en el proyecto. Saludos,
main
o winmain
? Gracias
Para resumir la publicación anterior de Cheers y hth. - Alf, asegúrate de tener main()
o WinMain()
definido y g ++ debería hacer lo correcto.
Mi problema fue que main()
se definió dentro de un espacio de nombres por accidente.
Me encontré con este error al compilar mi aplicación con SDL. Esto se debió a que SDL definió su propia función principal en SDL_main.h. Para evitar que SDL defina la función principal, se debe definir una macro SDL_MAIN_HANDLED antes de que se incluya el encabezado SDL.h.
Intente guardar su archivo .c antes de compilar. Creo que su computadora está haciendo referencia a una ruta a un archivo sin información dentro de él.
- Tuve un problema similar al construir proyectos C
Compruebe que todos los archivos estén incluidos en su proyecto:
Tuve este mismo error emergente después de actualizar cLion. Después de horas de retoques, noté que uno de mis archivos no estaba incluido en el objetivo del proyecto. Después de agregarlo de nuevo al proyecto activo, dejé de obtener la referencia indefinida a winmain16 y el código se compiló.
Editar: también vale la pena verificar la configuración de compilación dentro de su IDE.
(No estoy seguro de si este error está relacionado con la actualización reciente del IDE; podría ser causal o simplemente correlativo. ¡No dude en comentar cualquier información sobre ese factor!)
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. ¿Hay alguna manera de hacerloEclipse CDT
ya que no estoy usando la línea de comando? Gracias