Как вручную инициализировать среду выполнения c в exe?

Я пытаюсь предоставить собственную точку входа в исполняемый файл Visual C++, используя переключатель компоновщика "/entry". Соответствующая документация Microsoft содержит некоторые подробности о том, как вручную инициализировать среду выполнения c в dll, но я не могу понять, как инициализировать ее в моем exe-файле. Лучшее, что у меня есть, - это то, что мне нужно вызывать _CRT_init, но я не знаю, является ли это функцией или макросом, или где она может быть определена, а Visual Studio (и msbuild) не распознает идентификатор, поэтому никаких намеков там нет.

Обоснованием здесь является то, что я пытаюсь выполнить модульное тестирование с помощью Google Test, исполняемого файла, и он не будет связываться, потому что main() конфликтует. Два подхода, упомянутые в FAQ по GTest, на самом деле не могут быть обобщены и потребуют значительной доработки для реализации около 30 устаревших исполняемых файлов. Переименование main() каждого модульного тестового приложения кажется очень простым подходом, если бы я только мог инициализировать среду выполнения c.

2 ответа

Решение

Итак, я искал источник C Runtime сегодня днем, и ответ "нет". Вы не можете предоставить свою собственную исполняемую точку входа без имени main если вы хотите использовать C Runtime. Совсем помимо _CRT_INIT() будучи функцией инициализации для DLL (mainCRTStartup() является одной из функций инициализации для исполняемых файлов), mainCRTStartup() и это как вызов main() по имени.

  • Вы можете инициализировать CRT в отдельном модуле-обертке, который имеет main; obj1
  • Переименуйте основной из всех существующих модулей exe в xx_main; obj2, obj3.... objn
  • Ссылка obj1 (главная) с (obj2, obj3.... objn).

Чтобы протестировать файл foo.cc, вам нужно скомпилировать и связать его с вашей программой модульного тестирования.

В чем проблема с этой схемой?

введите описание изображения здесь

Хотя это и не задокументировано, можно инициализировать CRT в исполняемом файле таким же образом, как это можно сделать в DLL.

EXTERN_C BOOL WINAPI _CRT_INIT( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved );

// ThreadProc for CreateRemoteThread, a possible use case.
DWORD WINAPI ArbitraryAlternateEntryPoint( LPVOID )
{
    _CRT_INIT( GetModuleHandle( NULL ), DLL_PROCESS_ATTACH, NULL );

    // CRT functions can be used here.

    _CRT_INIT( GetModuleHandle( NULL ), DLL_PROCESS_DETACH, NULL );

    return 0;
}

Документация предполагает, что _CRT_INIT должен вызываться для каждого нового потока в дополнение к начальному вызову, но на практике это необязательно.

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