Ответ 1
Вы можете определить функцию on-load для библиотеки linux с помощью механизма .init
. Это то же самое, что и указание точки входа времени загрузки для двоичного файла (например, использование чего-то другого, кроме основного, как точки входа для программы).
При непосредственном соединении с помощью ld
вы используете:
-init <function name>
или если вы используете cc/gcc для связи, вы используете:
-Wl,-init,<function name>
Это самый простой уровень.
Edit
Для деструкторов/финализаторов используется механизм .fini
. Это работает так же, как опция init, и вы используете:
-fini <function name>
при вызове ld
. Доступность ограничена опцией -init
на платформе Mac OSX.
Вы также можете использовать синтаксис __attribute__((constructor))
для gcc:
static void con() __attribute__((constructor));
void con() {
printf("I'm a constructor\n");
}
Скорее всего, это более переносимый способ, а не зависание с вариантами компоновщика. Все конструкторы должны вызываться во время загрузки, но не зависят от порядка их инициализации, что приводит к безумию и невоспроизводимым ошибкам, которые требуют времени и усилий для отладки.
Изменить 2 Использование семантики __attribute__((constructor))/__attribute__((destructor))
является наиболее предпочтительным механизмом для языка программирования C/С++.
Для языка программирования D
вы должны действительно использовать конструктор/деструктор статического модуля:
static this() {
printf("static this for mymodule\n");
}
static ~this() {
printf("static ~this for mymodule\n");
}
Или статический конструктор классов:
class Foo {
static this() {
printf("static this for Foo\n");
}
}
Это сильно намечено в написании win32 DLLS и в спецификации языка относящейся к статическим конструкторам/деструкторам.
Изменить 3. Вам нужно будет указать ссылку .o
, которая экспортирует подпрограммы конструктора/деструктора, что позволит использовать статические инициализаторы. Поскольку все, что он должен делать, это вызвать Runtime.initialize(), это фактически вызывает все статические конструкторы/деструкторы в коде D
.
Код заглушки для инициализатора (в файле с именем myshared.d
):
import core.runtime;
extern (C) {
void attach();
void detach();
}
export void attach() {
Runtime.initialize();
}
export void detach() {
Runtime.terminate();
}
Создайте .o для этого заглушки:
dmd -m32 -c myshared.d
Проверьте имена функций attach/detach:
nm myshared.o
Показывает (среди других выходных данных):
0000001c S _D8myshared6attachFZv
00000034 S _D8myshared6detachFZv
образец кода .c для вызова этого (так называемый export.c в этом случае), мы ссылаемся на имена экспортированных подпрограмм из файла my shared.o
:
extern void D8myshared6attachFZv(void);
extern void D8myshared6detachFZv(void);
void __attach(void) __attribute__((constructor));
void __detach(void) __attribute__((destructor));
void __attach(void)
{
D8myshared6attachFZv();
}
void __detach(void)
{
D8myshared6detachFZv();
}
Обратите внимание, что в ссылках extern void
необходимо использовать измененное имя экспортируемой функции. Они должны совпадать или код не будет связан.
скомпилируйте код C, используя:
gcc -m32 -c export.c
свяжите файлы .c.o и .d.o вместе, используя:
cc -o libmyshared.dylib -m32 -shared myshared.o export.o -lphobos2
Предполагая, что библиотека phobos2 находится в вашем стандартном пути поиска ссылок. Недостатки -m32
опций для компилятора и компоновщика состоят в том, что версия компилятора D, которую я построил локально, поддерживала только 32-разрядную версию.
Это создает .dylib, с которым можно связать. Кажется, это работает на основе ограниченного тестирования, которое я выполнял. Похоже, что поддержка общих объектов/динамических библиотек очень ограничена, поэтому есть хорошие шансы на преодоление другого препятствия.