2008-11-20 7 views
7

Estoy tratando de construir una aplicación de consola sin usar el CRT, o cualquier otra importación que kernel32.lib en cualquier caso. Consigo mi código para compilar, pero no puedo envolver el enlazador en torno a algunos problemas:¿Construir aplicaciones de consola sin CRT y encabezados predeterminados?

unresolved external symbol @[email protected] 
unresolved external symbol "int __cdecl FreeLibrary(void *)" ([email protected]@[email protected]) 
unresolved external symbol "void * __cdecl LoadLibraryW(wchar_t *)" ([email protected]@[email protected]) 
unresolved external symbol "int (__cdecl*__cdecl GetProcAddress(void *,char *))(void)" ([email protected]@[email protected]) 
unresolved external symbol _wmainCRTStartup 

FreeLibrary, LoadLibraryW y GetProcAddress He traído a programar de forma explícita, no usar windows.h:

#pragma comment(lib, "kernel32.lib") 

typedef int(*FARPROC)(); 

void* LoadLibraryW(wchar_t* lpLibFileName); 
FARPROC GetProcAddress(void* hModule, char* lpProcName); 
int FreeLibrary(void* hLibModule); 

Supongo que algo anda mal con mis prototipos. Sin embargo, el problema más grande es __security_check_cookie y _wmainCRTStartup, que obviamente tienen algo que ver con el CRT. Así que me pregunto cómo voy a sobreescribir el valor predeterminado int wmain(int argc, wchar_t* argv[]) para el punto de entrada, y cómo deshacerme de lo que sea la cookie de seguridad.

Respuesta

4

_wmainCRTStartup es la función que llama a wmain()

IIRC que debería estar disponible en algún archivo .o que se puede enlazar con, busque en su directorio lib.

Tal vez esta es una lectura útil también: Reduce EXE and DLL Size with LIBCTINY.LIB (y Matt Pietrek rocas :-)

1

Puede buscar en Windows.h los prototipos que necesita para sus importaciones de kernel32. En general, las funciones de Windows se definen WINAPI que en realidad es __stdcall y no __cdecl. Eso solucionará ese problema al menos.

En cuanto a su otro problema, debe explorar los argumentos de la línea de comando del vinculador y ver si hay una forma de conseguir que no busque elementos desde CRT. No sé si hay una manera de hacer eso o no. Pero vas a tener que encontrar la forma o definir esas funciones tú mismo (que probablemente no quieras).

Recomendaría simplemente usar un compilador/enlazador diferente.

+0

En realidad los probé como llamadas estándar ya, y no resolvió el problema. – anon6439

0

El punto de entrada correcto es main(), no wmain() (ya que está compilando una aplicación de consola). El código de la cookie de seguridad se puede cortar desde el código fuente CRT; sin necesidad de vincular en.

+0

wmain es el punto de entrada de la consola para Unicode. – anon6439

1

tiene que declarar funciones windows.h como extern "C".

+0

¡Gracias! Esto lo resolvió. – anon6439

3

Bueno, respondiéndome aquí para resumir, en caso de que alguien más encuentre esta página buscando información.

Como se recomendó MSalters, el código de la cookie de seguridad puede ser robado de la fuente CRT, pero al hacer eso encontré que la bandera del compilador /GS- se puede usar para evitar por completo las cuestiones de seguridad.

Como dijo SoapBox, las funciones de API deben ser __stdcall, así como también el punto de entrada. He solucionado el problema del punto de entrada con el indicador de línea de comando del enlazador /entry:wmain.

Y, por último, como señaló Tomek, ¡las funciones de la API deben estar en el exterior C!

Así:

#pragma comment(lib, "kernel32.lib") 

typedef int(*FARPROC)(); 

extern "C" { 
    void* __stdcall LoadLibraryW(wchar_t* lpLibFileName); 
    FARPROC __stdcall GetProcAddress(void* hModule, char* lpProcName); 
    int __stdcall FreeLibrary(void* hLibModule); 
    typedef int (__stdcall *f_MessageBoxW_t)(unsigned long hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned long uType); 
    f_MessageBoxW_t fnMsg; 
    void* hUser; 
}; 

int __stdcall wmain(int argc, wchar_t* argv[]) 
{ 
    hUser = LoadLibraryW(L"user32.dll"); 
    fnMsg = (f_MessageBoxW_t)GetProcAddress(hUser, "MessageBoxW"); 
    fnMsg(0, L"foo", L"bar", 0); 
    FreeLibrary(hUser); 
    return 0; 
} 
+1

Estaba escribiendo una respuesta que incluía la opción '/ entry' cuando noté que tu auto-respuesta tiene casi todo excepto: 1. Incluir' windows.h' no dañará el tamaño de tu ejecutable un bit. Use '#define WIN32_LEAN_AND_MEAN' y' #define WIN32_EXTRA_LEAN' si quiere estar realmente seguro. Los encabezados Win32 no incluyen encabezados CRT, por lo que no habrá problemas aquí. 2. Probablemente ya esté haciendo esto, pero pase '/ NODEFAULTLIB' al enlazador y enlace a kernel32.lib, etc. manualmente. Esto realmente baja mucho el tamaño del ejecutable resultante. – rubenvb

2

Más correcta declaración punto de entrada será:

int __stdcall wmain(PVOID ThreadParam) 

Sin CRT punto de entrada llamado directamente por BaseThreadInitThunk. Su pase apunta a algo, pero no a argc + argv.

Cuestiones relacionadas