реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> C++Builder объявление экспортируемых из .dll функций
Nikolai Rihkov
сообщение Nov 25 2013, 08:43
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 286
Регистрация: 4-02-08
Пользователь №: 34 730



Здравствуйте!
Работаю с Borland C++Builder 6 пробую подключить библиотеку .dll создал файлы .lib и .def как положено, но вот что то не получается с объявлением в моем Unit1.h экспортируемых из .dll функций, в основном я делаю так _declspec(dllexport) _stdcal void usb_init(void); сдесь все работает, но не могу понять что делать, как объявить в моем Unit1.h экспортируемую из .dll функцию usb_get_busses(void); как указатель на структуру struct usb_bus *usb_get_busses(void);?
Код

struct usb_bus
{
    struct usb_bus *next, *prev;

    char dirname[LIBUSB_PATH_MAX];

    struct usb_device *devices;
    unsigned long location;

    struct usb_device *root_dev;
};

Go to the top of the page
 
+Quote Post
XVR
сообщение Nov 25 2013, 10:31
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Во первых - dllimport (а не dllexport)
Во вторых - не забудьте extern "C" {} вокруг импортируемых функций
Цитата
но не могу понять что делать, как объявить в моем Unit1.h экспортируемую из .dll функцию usb_get_busses(void); как указатель на структуру struct usb_bus *usb_get_busses(void);?

Так и объявлять -
Код
extern "C" {
__declspec(dllimport) __stdcall usb_bus *usb_get_busses(void);
}

PS. Если dll писалась не в Bulder, то скорее всего работать не будет, как функцию не объявляй sad.gif
Go to the top of the page
 
+Quote Post
Nikolai Rihkov
сообщение Nov 25 2013, 15:42
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 286
Регистрация: 4-02-08
Пользователь №: 34 730



dll писалась не в Bulder, работать эта функция не хочет, может можно как то по другому ее объявить, другой подход к проблеме?
Go to the top of the page
 
+Quote Post
XVR
сообщение Nov 25 2013, 17:52
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(Nikolai Rihkov @ Nov 25 2013, 19:42) *
dll писалась не в Bulder, работать эта функция не хочет, может можно как то по другому ее объявить, другой подход к проблеме?

Посмотрите под каким именем эта функция экспортируется из dll (через любой дампер, который умеет дамповать секцию экспорта). И еще посмотрите, что dll импортирует. Если там есть рантайм библиотеки VC, то скорее всего дело швах - они с BCB не совместимы
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 25 2013, 22:00
Сообщение #5


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(XVR @ Nov 25 2013, 21:52) *
Посмотрите под каким именем эта функция экспортируется из dll (через любой дампер, который умеет дамповать секцию экспорта). И еще посмотрите, что dll импортирует. Если там есть рантайм библиотеки VC, то скорее всего дело швах - они с BCB не совместимы

Странно. А я подцепляю к Builder 6.0 математическую библиотеку Intel MKL, писанную под VS2013, и всё нормально работает. Точно так же получилось пристыковать код dll-ки, написанный и скомпилированной на Фортране (как на Compaq Visual Fortran Professional v6.5, так и на Intel Fortran Composer XE 2013. В последнем случае пришлось повозиться, подбирая опции линкера).

Я, конечно, не уверена, что пристыковать можно любую библиотеку, но в большинстве случаев это получается.

Методика такая:
Первым делом снимаем с dll-файла дамп, напуская на него tdump.exe, входящий в состав Билдера. Лучше с выдачей в файл:
tdump xxx.dll > xxx.dmp
Потом вручную просматриваем файл xxx.dmp на предмет того, как в нем прописаны имена экспортируемых функций, обращая внимание на два обстоятельства: стоит ли спереди подчеркивание и есть ли в именах малые/строчные буквы.
Следом за этим генерим к этой dll-ке lib-файл. Если таковой уже прилагается, то выбрасываем его прочь, т.к. пристыковать его ни за что не получится - у VS слишком специфический формат объектных модулей и библиотек. Поэтому создаем свой lib-файл с помощью утилиты implib.exe (из того же Билдера). Делаем это так:
implib.exe -a -c xxx.lib xxx.dll > xxx.lst
xxx.lst - это просто листинг на предмет ошибок, его лучше сохранить, т.к. по экрану пробежит очень быстро.
xxx.dll - наша dll-ка.
xxx.lib - имя генерируемой либы (обычно с тем же именем, как у dll, только с другим расширением).
Но самое важное - это опции -a и -c
-a ставим только тогда, когда имена функций идут с передним подчеркиванием (для этого дамп делали!), иначе пропускаем.
-с ставим только тогда, когда имена функции содержат малые буквы (наряду с большими), иначе пропускаем.
Получаем в результате либу xxx.lib, которую добавляем в свой проект, а dll-ку xxx.dll кладем в тот же директорий рядышком (ее в проект добавлять не надо).
Вот и всё.

Но всё это только в отношении стыковки, тогда как при запуске проекта нужно быть готовыми к любой неожиданности.
Первая из них - если наша dll-ка при запуске позовет другую. Такое встречается почти всегда, поскольку dll-ки в момент запуска аллокируют память с помощью функций CALLOC/MALLOC, которых в себе не содержат. Если dll-ка старенькая, то, скорее всего, она найдет себе msvcr.dll среди компонентов Window. Но в моем случае пришлось добывать и подкладывать рядом msvcr100.dll из VS2013 Redistributable Pack или инсталлировать его.

Далее. Не плохо было бы встать отладчиком (поставить breakpoint) на CALL-вызове функции из данной dll-библиотеки, чтобы проверить, сохраняется ли указатель стека, до и после ее выполнения. Если же код сишный, то в норме програма должна восстановить указатель стека к прошлому значению на следуюших 1-2 шагах. Если этого не происходит, то ситуация становится серьезной и требует корректировки объявления функции в хидере. Но тут давать какие-то советы вперед бесполезно - надо разбираться с конкретным примером.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Nov 26 2013, 18:07
Сообщение #6


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Xenia @ Nov 26 2013, 02:00) *
...Не плохо было бы встать отладчиком...


всё верно описано.
можно добавить, что:
подчёркиваниями кодируют кто чистит стэк (вызывающий или вызываемый).
под отладчиком лучше не только (и не столько) проверить стэк, как пройтись по шагам на предмет чтения(ожидания) вызываемой функции
ваших переменных. Так например тот же фортран всегда оперирует указателями, в watcome чистка стэка идёт (как правило) внутри
вызываемой функции, кларион имеет свои заморочки по типам и способам передачи параметров, клипер например свои...и т.д. и т.п..

вязать можно практически всё, что вздумается. на передний план выходит обычно целесообразность всего этого огорода...

Сообщение отредактировал kolobok0 - Nov 26 2013, 18:07
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 05:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01386 секунд с 7
ELECTRONIX ©2004-2016