Вы можете определить функцию загрузки для библиотеки linux, используя механизм .init
.Это то же самое, что и указание точки входа во время загрузки для двоичного файла (например, использование в качестве точки входа для программы чего-то отличного от main).
При прямом связывании с использованием ld
вы используете:
-init <function name>
или если вы используете cc / gcc для ссылки, вы используете:
-Wl,-init,<function name>
Это на самом простом уровне.
Редактировать Для деструкторов / финализаторов вы используете механизм .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");
}
Что, вероятно, является болеепортативный способ, а не прикручивание с компоновщиком опций.Все конструкторы должны вызываться во время загрузки, но не не зависят от порядка их инициализации, что приводит к безумию и невоспроизводимым ошибкам, которые требуют времени и усилий для отладки.
Edit 2 Использование семантики __attribute__((constructor))/__attribute__((destructor))
является наиболее предпочтительным механизмом для языка программирования C / 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 и в спецификации языка относящиеся к статическим конструкторам / деструкторам .
Edit 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
Проверьте имена функций присоединения / отсоединения:
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
свяжите файлы .co и .do вместе, используя:
cc -o libmyshared.dylib -m32 -shared myshared.o export.o -lphobos2
Предполагается, что библиотека phobos2 находится в вашем стандартном пути поиска компоновщика.Значения параметров -m32
для компилятора и компоновщика связаны с тем, что версия компилятора D, которую я создал локально, поддерживает только 32-битную версию.
Это создает файл .dylib, с которым можно связать.Кажется, это работает на основе ограниченного тестирования, которое я провел.Похоже, что поддержка общих объектов / динамических библиотек очень ограничена, поэтому есть большая вероятность, что будет преодолено еще одно препятствие.