elelel / qluacpp-tutorial

Tutorial for Qluacpp library (C++ interface for Quik trading terminal)
27 stars 13 forks source link

подключение dll на c++ #6

Open QApplication opened 7 years ago

QApplication commented 7 years ago

При подключении сторонних dll с++ падает quik. Наверное это связано с тем, что при компиляции проиходит декорация имен в dll на с++ и не возможно найти нужную функцию в подключаемой к quik dll (экспорт через extern "C" {...}).

Вопрос! Cуществуют ли способы решения этой проблемы без написания обертки на С для подключаемой dll c++? Что нужно делать если необходимо экспортировать класс из dll c++?

elelel commented 7 years ago

Не совсем понял, какие dll в каком месте подключаются. По идее не должно быть связано с extern "C", оно же относится только к экспорту плагиновой dll для Квика, а импортирует плагиновая dll для Квик C++ как импорты функции, экспортированные как C++ из сторонней DLL

QApplication commented 7 years ago

Из предыстории:

  1. Подключаю, например к Вашему проекту basic_tutorial, исходники QCustomPlot и создаю посльзовательский ui, собираю проект на Qt под gcc - ошибок нет. Далее смотрим структуру получившейся dll. Выясням, что прилинкована еще Qt5GUI.dll. Собираем все dll в нужной директории. При запуске скрипта возникает ошибка (не найдены спецаильные процедуры). Убираем ui на qt и оставляем в проекте только исходники QCustomPlot - результат аналогичный.
  2. Упрощаем задачу. Создаем с++ dll с процедурой экспорта одного созданного класса__declspec( dllexport ). Подключаем ее к проекту basic_tutorial как внешнюю dll. Собираем все вместе и запускаем. Результат как п.1.
  3. Создаем обертку для dll c++ с процедурой экспорта extern "C" __declspec( dllexport ) и реализуем в ней класс и метод из dll c++. Собираем и запускам. Все работает. Вопрос: можно ли использовать скомпилированные c++ dll и подключать их как внешние непосредственно в исходный проект без написания обертки с процедурой экспрорта extern "C" __declspec( dllexport ). Если эспользуется одна функция - то в этом проблем нет, а если целые классы и заимствованные dll, то это трудозатратно.

PS: пробовал собирвать по п.2 через cmake по примеру в basic_tutorial. Результат идентичен как на Qt, так и на cmake.

elelel commented 7 years ago

Добавил пример basic_dll, как создать и подключить внешнюю DLL с C++ интерфейсом

QApplication commented 7 years ago

Спасибо за материал. Что делать если от подключаемой dll есть только заголовочные файлы, lib файл для линковки и бинарник?

elelel commented 7 years ago

То же самое что и в примере, просто шаг компиляции самой DLL не нужен. Заголовочный файл, который у вас есть в этом случае эквивалентен cpp_dll.hpp в котором cpp_dll_EXPORT всегда указывает на то, что это файл для импорта сторонней библиотеки во внешние проекты.

QApplication commented 7 years ago

Спасибо. Попробую собрать.

QApplication commented 7 years ago

Посмотрел на файл экспорта cpp_dll_export.hpp и увидел конструкцию для экспорта классов define cpp_dll_EXPORT __declspec(dllexport). Такой же макрос я и у себя писал, только это не помогает. Собственной запустил ваш пример и получил аналогичную ошибку загрузки модуля: error loading module 'lualib_basic_dll' from file '......\qluacpp\dll\lualib_basic_dll.dll': The specified module could not be found. Интересно, у вас работает?

elelel commented 7 years ago

Да, все что я публикую в репо tutorial я проверяю сначала у себя. Текст ошибки, который вы привели, говорит о скорее о том, что в файле lua вы указали неправильный путь к длл плагина (не внешней длл).

elelel commented 7 years ago

Кстати, нужно учитывать правила поиска DLL для процесс info.exe, как и при любой работе с dll. https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx

QApplication commented 7 years ago

Вы правы. подключаемую cpp_dll.dll положил к скрипту lua (ранее она находилась рядом с lualib_basic_dll в cd/dll) и все заработало.

elelel commented 7 years ago

А скрипт, наверное находится в той же директории, где info.exe? Вообще с Квиком использовать статично-линкованные длл без проблем есть два способа: класть все прямо в директорию Квика, где info.exe (это для больше подходит для личных скриптов), либо писать инсталлятор, который будет инсталлировать длл в system32 (это больше для скриптов "на продажу").

QApplication commented 7 years ago

у меня наоборот ситуация: я бинарники положил в папку dll на один уровень ниже и написал путь к нему до require следующий package.cpath = "c:\\ATON\\QUIK\\Lua_script\\qluacpp\\dll\\?.dll"; Так вот основную загружаемую dll (lualib_basic_dll.dll) он находит в каталоге c:\ATON\QUIK\Lua_script\qluacpp\dll, а вот подключаемая бибилиотеке cpp_dll.dll должна лежать рядом с lua скриптом. Мне непонятно почему не находит ее в папке dll, так как я не писал имя dll в cpath - ...\dll\?.dll

QApplication commented 7 years ago

для инключения таких случаев проще все ложить в корень к info.exe

elelel commented 7 years ago

package.cpath - это для лоадера lua А Windows, когда грузит DLL, которые в импортах к основной DLL (которая была найдена по этой package.cpath лоадером lua) ищет их в соответствии с указанными выше правилами

QApplication commented 7 years ago

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

QApplication commented 7 years ago

Разобрался со своей первоначальной проблемой с подключением dll с++: dependency walker показал, что присоединена только одна внешняя dll qt5core.dll. Собственно я и пытался скопировать ее во всевозможные места и не помогало вот и решил спросить у Вас. Однако, первоначальную dll собрал в виде апликухи и проверил другой программой на наличие подключаемых модулей - нашлось гораздо больше динамически используемых dll. Скопировал их и все заработало. Спасибо за советы и думаю тему с подключением dll на c++ можно закрыть.

elelel commented 7 years ago

Я пока оставлю ваши вопросы, из них можно сделать неплохую документацию в стиле faq, если дойдут руки, конечно :)