Я пытаюсь написать программу на C ++ без main. Можно ли изменить точку входа исполняемого файла mach-o на пользовательскую функцию (кроме main()
)?
Если нет, то можно ли обернуть main
назвать мою версию основного до фактического C main
называется?
Редактировать:
Я хочу, чтобы моя пользовательская функция вызывала C main
, Если бы я дал ему атрибут конструктора или добавил его в список ctor, то main
будет вызван дважды. Я не хочу, чтобы это произошло.
P.S Я создаю исполняемые файлы в Mac OS X High Sierra с версией Clang 9.1.0
Вы можете использовать -e <symbol>
опция ld, которую вы можете вызвать как -Wl,-e,_<symbol>
из лязга Исторически, точка входа в программу будет _start
от crt0.o, однако это не было делом в Дарвине со времен Mac OS X 10.8 и iOS 6.0, где LC_MAIN
была введена команда загрузки (замена LC_UNIXTHREAD
). «Старый» способ все еще может быть использован, но должен быть явно включен с -no_new_main
флаг компоновщика (который имеет аналог -new_main
Если вам это когда-нибудь понадобится). Обязанность, некогда выполняемая crt0.o, была перенесена на динамический компоновщик, /usr/lib/dyld
, который может обрабатывать как LC_MAIN
а также LC_UNIXTHREAD
по мере необходимости.
Так, учитывая программу на C с main
:
// t.c
#include <stdio.h>
int main(int argc, const char **argv)
{
printf("test %i\n", argc);
return 0;
}
Вы можете легко создать файл C ++, например так:
// t.cpp
extern int main(int, const char**);
extern "C" int derp(int argc, const char **argv)
{
return main(0, (const char*[]){ (const char*)0 });
}
И скомпилируйте их с clang++ -o t t.cpp -xc t.c -Wl,-e,_derp
,
Просто не забудьте либо объявить derp
как extern "C"
или укажите искаженный символ в командной строке.
Вы также можете проверить полученный исполняемый файл с помощью otool
чтобы убедиться, что он использует LC_MAIN
скорее, чем LC_UNIXTHREAD
:
bash$ otool -l ./t | fgrep -B1 -A3 LC_MAIN
Load command 11
cmd LC_MAIN
cmdsize 24
entryoff 3808
stacksize 0
Вы можете передать -e <symbol name>
вариант для компоновщика (ld
) указать другую точку входа. Точка входа по умолчанию не main
; его start
который предоставляется crt1.o и который, в свою очередь, вызывает main
,
Вы можете использовать _start()
Он устанавливает некоторые вещи, заполняет массив аргументов argv
, считает, сколько аргументов есть, а затем вызывает main
, После main
возвращается, exit
называется.
Вот несколько ссылок:
https://stackoverflow.com/a/29694977/2302572
http://learningpearls.blogspot.com/2011/02/start-function-inside-c.html