Проблемы с использованием скриптового домена в MinGW

Я хочу воспроизвести этот код Perl на C, объединяя API и CLI в одном и том же файле исходного кода C ( scriptedmain). Это сделано в Python с if __name__=="__main__": main() и в gcc/Unix это выглядит так:

$ gcc -o scriptedmain scriptedmain.c scriptedmain.h
$ ./scriptedmain
Main: The meaning of life is 42
$ gcc -o test test.c scriptedmain.c scriptedmain.h
$ ./test
Test: The meaning of life is 42

scriptedmain.h

int meaning_of_life();

scriptedmain.c

#include <stdio.h>

int meaning_of_life() {
    return 42;
}

int __attribute__((weak)) main() {
    printf("Main: The meaning of life is %d\n", meaning_of_life());

    return 0;
}

test.c

#include "scriptedmain.h"
#include <stdio.h>

extern int meaning_of_life();

int main() {
    printf("Test: The meaning of life is %d\n", meaning_of_life());
    return 0;
}

Однако, когда я пытаюсь скомпилировать с помощью gcc/Strawberry, я получаю:

C:\>gcc -o scriptedmain scriptedmain.c scriptedmain.h
c:/strawberry/c/bin/../lib/gcc/i686-w64-mingw32/4.4.3/../../../../i686-w64-mingw32/lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o): In function `main':
/opt/W64_156151-src.32/build-crt/../mingw-w64-crt/crt/crt0_c.c:18: undefined reference to `WinMain@16'
collect2: ld returned 1 exit status

И когда я пытаюсь скомпилировать с помощью gcc/MinGW, я получаю:

$ gcc -o scriptedmain -mwindows scriptedmain.c scriptedmain.h
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../libmingw32.a(main.o):main.c:(.text+0x104): undefined reference to `WinMain@16'
collect2: ld returned 1 exit status

Как я могу получить GCC в Windows, чтобы распознать __attribute__((weak)) синтаксис?

Также G++ показывает ту же ошибку.

2 ответа

Я нашел решение, которое работает в Windows и Unix: просто обернуть main() в инструкциях препроцессора, которые его опускают, если не установлены явные флаги компилятора.

scriptedmain.c:

#include <stdio.h>

int meaning_of_life() {
    return 42;
}

#ifdef SCRIPTEDMAIN

int main() {
    printf("Main: The meaning of life is %d\n", meaning_of_life());

    return 0;
}

#endif

Сейчас main() будет полностью опущен, если вы не скомпилируете

gcc -o scriptedmain -DSCRIPTEDMAIN scriptedmain.c scriptedmain.h

Этот код безопасно импортировать в другой C-код, потому что препроцессор будет удален main()оставляя вас, чтобы закодировать свой собственный основной. Самое приятное, что это решение больше не зависит от непонятных макросов компилятора, а только от простых инструкций препроцессора. Это решение работает и для C++.

Это не очень хорошая практика в C независимо от операционной системы. Лучшая практика в C для чего-то достаточно сложного, чтобы его можно было разделить на библиотеку и драйвер, это поместить main в файле все само по себе.

Другие вопросы по тегам