Я хочу создать динамическую библиотеку (кросс-платформу) в D, поэтому я сделал несколько Google. Через некоторое время я нашел this. Я абсолютно ошеломлен тем, насколько сложны в письменной форме, компиляция и даже привязка к DLL. Разве нет единого способа создания общей библиотеки, как в C? (просто оставьте основную функцию и передайте некоторые флагов в компоновщик)Как создать динамическую библиотеку в D?
ответ
Ну, я решил потратить некоторое время на то, чтобы сегодня испортить это, и у меня есть что-то, что работает, по крайней мере, если основная программа также написана в D (в Linux, я думаю, он будет работать с C тоже на Windows. Причина в том, что я не ссылался на phobos в .so в D, поэтому он полагается на exe для этих символов. Я думаю, tbh I не знаю точно, что здесь происходит, может быть, это сработает лучше, если я тоже воспользуюсь общей библиотекой phobos).
В любом случае, во-первых, давайте бросим код.
Это testdll.d и строит наша длл
module testdll;
import std.stdio;
extern(C)
export void lol() {
import core.stdc.stdio;
printf("hello from C\n");
writeln("hello!");
}
version(Windows)
extern(Windows) bool DllMain(void* hInstance, uint ulReason, void*) {
import std.c.windows.windows;
import core.sys.windows.dll;
switch (ulReason)
{
default: assert(0);
case DLL_PROCESS_ATTACH:
dll_process_attach(hInstance, true);
break;
case DLL_PROCESS_DETACH:
dll_process_detach(hInstance, true);
break;
case DLL_THREAD_ATTACH:
dll_thread_attach(true, true);
break;
case DLL_THREAD_DETACH:
dll_thread_detach(true, true);
break;
}
return true;
}
Вы заметите, что большинство кода является WinMain, который просто вызывает druntime функции. Я думаю, что основная часть должна быть доступна, по крайней мере, в виде микса или, может быть, даже полностью автоматической, так как это чистый шаблон.
И код клиента:
import core.runtime;
alias extern(C) void function() functype;
version(Posix) {
extern(C) void* dlsym(void*, const char*);
extern(C) void* dlopen(const char*, int);
extern(C) char* dlerror();
pragma(lib, "dl");
} else version(Windows) {
extern(Windows) void* LoadLibraryA(const char* filename);
extern(Windows) void* GetProcAddress(void*, const char*);
}
void main() {
version(Posix) {
auto thing = dlopen("./testdll.so", 2);
if(thing is null) {
import std.conv;
import std.stdio;
writeln(to!string(dlerror()));
return;
}
auto proc = cast(functype) dlsym(thing, "lol");
} else version(Windows) {
auto thing = LoadLibraryA("testdll.dll");
assert(thing !is null);
auto proc = cast(functype) GetProcAddress(thing, "lol");
}
assert(proc !is null);
//import std.stdio; writeln("calling proc");
proc();
}
Это имеет другой код для ОС Windows и Linux, хотя это очень похоже. Предполагается, что материал для прослушивания начнет заботиться об этом в ближайшее время, как мы упоминали в комментариях.
Команды компиляции не так уж плохи, но немного странные. Linux:
dmd -fPIC -shared testdll.d -defaultlib= # builds the dll
PIC и поделились им, чтобы построить .so. Я сделал пустой defaultlib, потому что без него загрузка dll во время выполнения не удалась с ошибками «уже определенные символы».
Построение клиента проста:
dmd testdllc.d
Обратите внимание, что есть прагма (ОМТ) в файле, который связывает с -ldl вариант автоматически. Запустите его и получите привет! BTW убедитесь, что оба находятся в одном каталоге, так как это загружает ./ в загрузчик.
Теперь давайте построим на Windows.
dmd -oftestdll.dll -shared testdll.d testdll.def
рассказывайте вывести нашу DLL, использовать -shared поэтому он знает, и тогда другое дело файл Защиту, как описано здесь http://dlang.org/dll.html/dllmain
Это содержимое этого файла:
LIBRARY testdll
EXETYPE NT
CODE SHARED EXECUTE
DATA WRITE
EXPORTS
lol
Если вы не используете файл .def, dll будет успешно сгенерирована, но процедура не будет найдена, потому что она не экспортируется. (Я думаю, что ключевое слово export в D должно быть в состоянии сделать это автоматически, минуя hte .def файл, и я считаю, что есть дискуссия об этом, но сейчас это необходимо, насколько мне известно.)
И клиент так же легко:
dmd testdllc.d
Выполнить это и получить некоторые приветы, если все идет хорошо.
Теперь, почему я сделал псевдоним functype в клиенте? Легче, чем делать другие кастинга и т. Д., И это делает его красивым внешним (C).
Почему внешний вид функции lol (C) в первую очередь? Просто он имеет более легкое имя для использования в GetProcAddress/dlsym. Может также иметь прагму (mangle) или сделать .mangleof с импортом. Всевозможные варианты там, довольно простые, я просто хотел, чтобы это упростило, чтобы сделать тест легче сосредоточиться. «lol» - это более простое имя, чем «_D7testdll3lolFZv», или как бы искомое имя не было ... (OMG я правильно рубил его! Иногда я думаю, что пишу слишком много D lol), и да, это тоже работает делать глазным яблоком. Примечание. В Windows, файл .def, возможно, придется оставить верхний знак подчеркивания, если вы это сделаете.
В любом случае, да, это создало рабочую dll/so для меня и программу для ее загрузки и использования. Не так красиво, как может/должно быть, но это работает. По крайней мере, для меня.
Возможно, файл .def может не понадобиться. Я просто сделал несколько тестов с измененным именем, и он смог успешно загрузить его. Я думаю, что ошибка, которую я совершил, - это забыть о главном подчеркивании в GetProcAddress. Я также планирую отправить запрос на загрузку в druntime, который может предоставить бутылочный dllmain, который должен действительно свести на нет хлопот. –
- 1. Как создать статическую/динамическую библиотеку, которая использует библиотеку
- 2. Загрузить динамическую библиотеку по имени файла в D
- 3. Как скомпилировать динамическую библиотеку?
- 4. Невозможно создать динамическую библиотеку для PJSIP
- 5. Как создать динамическую библиотеку для проекта ios в xcode?
- 6. Как реализовать динамическую библиотеку Android
- 7. Невозможно загрузить динамическую библиотеку
- 8. Невозможно загрузить динамическую библиотеку php_ldap.dll
- 9. Невозможно загрузить динамическую библиотеку
- 10. Как создать динамическую библиотеку Cocoa (Obj-C) для OS X?
- 11. Включить динамическую библиотеку из сети
- 12. Компилировать как статическую и динамическую библиотеку
- 13. Как включить динамическую библиотеку tbb.so в Makefile?
- 14. Как использовать динамическую библиотеку C в C++?
- 15. Как преобразовать динамическую dll в статическую библиотеку?
- 16. Как включить динамическую библиотеку в C++
- 17. Как связать динамическую библиотеку в Xcode?
- 18. Как создать динамическую библиотеку DLL в C++, чтобы заменить устаревшую библиотеку Fortran DLL
- 19. г ++ связывающая статическую библиотеку в динамическую библиотеку (без -fPIC)
- 20. Как создать динамическую форму?
- 21. Как создать динамическую таблицу?
- 22. Как создать динамическую ссылку?
- 23. Как создать динамическую службу?
- 24. Apache: невозможно загрузить динамическую библиотеку
- 25. загрузить динамическую библиотеку из elisp
- 26. APC - Невозможно загрузить динамическую библиотеку
- 27. Как создать динамическую форму?
- 28. Как создать динамическую диаграмму?
- 29. Как создать динамическую сетку
- 30. Создайте динамическую библиотеку для выпуска и статическую библиотеку для GTest
Основная сложность исходит от GC, который необходимо связать и деинсталлировать во время выполнения. C не нуждается в том, что по умолчанию –
@ratchetfreak Есть ли причина, по которой это не делается автоматически? –
Реализация, которая делает все это автоматически во время выполнения, является неполной. Я начал писать ответ, чтобы показать, как его использовать, и обнаружил, что он не связан, поскольку функции еще не выполнены ... файл определения модуля в Windows тоже немного боль, поскольку ключевое слово export doesn ' Так много помогает. Там медленно продолжаются дебаты об исправлении, но эти вещи перетащить. Прямо сейчас, лучший способ сделать это - с достаточным количеством ручной работы, вызывая функции динамической библиотеки C для загрузки библиотеки самостоятельно ... –