2008-11-20 5 views
7

J'essaye de construire une application de console sans utiliser le CRT, ou d'autres importations que kernel32.lib dans tous les cas. Je reçois mon code pour compiler, mais ne peut pas envelopper l'éditeur de liens autour de quelques problèmes:Création d'applications de console sans CRT et en-têtes par défaut?

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 et GetProcAddress je l'ai amené à programmer explicitement, ne pas utiliser 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); 

Je suppose que quelque chose ne va pas avec mes prototypes. Cependant, le plus gros problème sont __security_check_cookie et _wmainCRTStartup, qui ont évidemment quelque chose à voir avec le CRT. Donc, je me demande comment je pourrais contourner la valeur par défaut int wmain(int argc, wchar_t* argv[]) pour entrypoint, et comment se débarrasser de ce que le cookie de sécurité est.

Répondre

4

_wmainCRTStartup est la fonction qui appelle wmain()

IIRC il devrait être disponible dans certains fichier .o que vous pouvez lier avec, regardez dans votre répertoire lib.

Peut-être est une lecture utile aussi: Reduce EXE and DLL Size with LIBCTINY.LIB (et Matt roches Pietrek :-)

1

Vous pouvez regarder dans Windows.h pour voir les prototypes dont vous avez besoin pour vos importations kernel32. En général, les fonctions Windows sont définies WINAPI qui est en fait __stdcall et non __cdecl. Cela réglera au moins ce problème.

Quant à votre autre problème, vous devez explorer les arguments de ligne de commande de l'éditeur de liens et voir s'il y a un moyen de l'obtenir de ne pas regarder les choses de CRT. Je ne sais pas s'il existe un moyen de le faire ou non. Mais vous allez devoir trouver un moyen ou définir ces fonctions vous-même (ce que vous ne voulez probablement pas faire).

je recommande simplement en utilisant un compilateur/éditeur de liens différents.

+0

En fait, je les ai déjà essayés en tant que stdcall, et cela n'a pas résolu le problème. – anon6439

0

Le bon point d'entrée est main(), et non wmain() (puisque vous compilez une application de console). Le code de cookie de sécurité peut être découpé à partir du code source CRT; pas besoin de lien dans.

+0

wmain est le point d'entrée de la console pour unicode. – anon6439

1

Vous devez déclarer les fonctions de Windows.h comme extern "C".

+0

Merci! Cela l'a résolu. – anon6439

3

Eh bien, me répondre ici pour résumer, au cas où quelqu'un d'autre trouve cette page à la recherche d'informations. Comme MSalters conseillé, le code de cookie de sécurité peut être volé à partir de la source CRT, mais ce faisant, j'ai trouvé que l'indicateur de compilateur /GS- peut être utilisé pour éviter la sécurité tout à fait.

Comme SoapBox dit, les fonctions de l'API doivent être __stdcall, ainsi que le point d'entrée ne. J'ai corrigé le problème du point d'entrée avec l'indicateur de ligne de commande de l'éditeur de liens /entry:wmain.

Et enfin, comme Tomek a souligné, les fonctions de l'API doit y être en C extern!

Alors:

#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

J'écrivais juste une réponse qui incluait l'option '/ entry' quand j'ai remarqué que votre réponse à moi-même avait à peu près tout sauf: 1. Inclure' windows.h' ne nuira pas à la taille de votre exécutable. Utilisez '#define WIN32_LEAN_AND_MEAN' et' #define WIN32_EXTRA_LEAN' si vous voulez être vraiment sûr. Les en-têtes Win32 n'incluent pas les en-têtes CRT, donc il n'y aura pas de problème ici. 2. Vous faites probablement déjà cela, mais passez '/ NODEFAULTLIB' à l'éditeur de liens et faites un lien vers kernel32.lib etc. manuellement. Cela réduit considérablement la taille de l'exécutable qui en résulte. – rubenvb

2

Plus déclaration de point d'entrée correcte sera:

int __stdcall wmain(PVOID ThreadParam) 

Sans point d'entrée CRT directement par l'BaseThreadInitThunk. Son passe pointeur vers quelque chose, mais pas argc + argv.

Questions connexes