Если вы используете GCC, вы можете использовать спецификатор __attribute__((constructor))
для запуска одного фрагмента кода при запуске (до main
) для каждого из ваших «модулей». (Также работает с Clang и ICC.)
Например:
$ cat t.c
#include <stdio.h>
#ifdef AAA
static void __attribute__((constructor)) myinit()
{
printf("%s\n", AAA);
}
#else
int main()
{
printf("bye\n");
return 0;
}
#endif
$ gcc -DAAA=\"hello\" -o m.o -c t.c
$ gcc -DAAA=\"there\" -o n.o -c t.c
$ gcc -o t.o -c t.c
$ gcc -o foo m.o n.o t.o
$ ./foo
there
hello
bye
(Код предоставлен только для иллюстрации.)
Как только у вас это получится, вы довольно хороши. Пусть эта функция «конструктор» сделает все, что нужно модулю для инициализации, и «зарегистрируется» в вашей структуре плагинов. (Структура со связкой указателей функций, добавленная в связанный список или что-то подобное, будет работать.)
Обратите внимание, что порядок ссылок будет определять порядок инициализации вашего плагина, и это может привести к появлению червей - если ваши модули зависят друг от друга, все становится действительно сложно. Убедитесь, что у вас есть как можно меньше глобалов.
Обновление:
Если вам нужно использовать статические библиотеки, а не простые .o
файлы, вам понадобится немного дополнительной магии компоновщика.
Предполагается, что вышеприведенное уже выполнено:
$ ar cru libm.a m.o
$ ar cru libn.a n.o
$ gcc -o foo t.c -Wl,-whole-archive libn.a libm.a -Wl,-no-whole-archive
$ ./foo
hello
there
bye
Я не совсем уверен, можете ли вы полагаться на (обратный) порядок ссылок в этом случае.
Или:
$ ar cru libmn.a m.o n.o
$ gcc -o foo t.c -Wl,-whole-archive libmn.a -Wl,-no-whole-archive
$ ./foo
there
hello
bye
(И здесь я понятия не имею, какой порядок вы получите.)