2007-08-20 - ANSI C - Portabilidade - WINMAIN LPSTR lpCmdLine to char **argv

20 de agosto

ANSI C - Portabilidade - WINMAIN LPSTR lpCmdLine to char **argv

Sempre tento criar minhas rotinas portáveis... mesmo que elas sejam apenas para aprendizado.

Recentemente testei o SDL_mixer que traz uma rotina exemplo bem legal de como funciona, roda todos os formatos suportados, wav, ogg, mp3... etc. Segue o link:
http://jcatki.no-ip.org/SDL_mixer/demos/
Mas enfrentei alguns problemas de compilação por causa dos argumentos passados pela linha de comando, com certeza a rotina foi desenvolvida em linux... aprecio isto... mas não acho interessante para um software ser restrito pelo sistema operacional, mesmo que este seja aberto.

Pesquisei coisas como LPSTR to char** e LPWSTR* to char* mas sem sucesso.

É, a microsoft sempre nos dá um trabalho extra totalmente desnecessário, mas vamos lá...

Como vocês já sabem (ou deveriam saber), o windows possui uma forma diferente de iniciar o programa.
ao invés do famoso, fácil e perfeito:
int main(int argc, char **argv)
ele usa
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR lpCmdLine, INT nShowCmd)


Assim sendo, você não tem o array para pegar is itens da linha de comando da forma que está acostumado.
Então tive que criar uma forma de resolver isto para que eu possa criar meu código sem me preocupar com OS em que está sendo compilado.

Segue:
#ifndef WIN32
int main(int argc, char **argv)
{
#else
#include <windows.h>
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR lpCmdLine, INT nShowCmd)
{
int argc;
char **argv;
LPWSTR *szArglist;
szArglist = CommandLineToArgvW(GetCommandLineW(), &argc);
int __i;
if( NULL == szArglist ) {
wprintf(L"CommandLineToArgvW failed\n");
return 0;
} else {
argv = malloc(sizeof(char *) * argc);
for( __i=0; __i<argc; __i++) {
int tmp = wcslen(szArglist[__i]);
char *c = malloc(sizeof(char) * tmp);
wcstombs(c, szArglist[__i], tmp);
argv[__i] = c;
}
}
// Free memory allocated for CommandLineToArgvW arguments.
LocalFree(szArglist);
#endif

// O código vem aqui...
// e vc pode acessar o argv normalmente:
int i;
for( i=0; i<argc; i++)
printf("%d: %s\n", i, argv[i]);
#ifdef WIN32
// Free memory allocated for CommandLineToArgvW arguments.
for ( __i = 0; __i < argc; __i++ )
free(argv[__i]);
free(argv);
#endif
return(0);
}

Me avise se isto for util pra você, ficarei feliz em saber.

Até a próxima,
Abs,
Ton

Comentários

Postagens mais visitadas