Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Использование библиотеки на D в коде C++ |
Автор: AlterMann 12.7.2013, 13:46 | ||||||
Здравствуйте, о многоуважаемые! ![]() Довелось мне познакомиться не так давно с интересным таким языком D. Но естественно сам по себе D как-то не очень доставляет, поскольку много кода уже написано на C++ и хотелось бы поэтому научиться дружить их вместе. Раньше я этого, к сожалению не делал, с другими языками. Только на С++ писал библиотеку и использовал в другом С++ коде. Итак, естественно почитав интернетов, написал следующее на D:
Данный код компилирую так: dmd -release -O -lib -odlib -oflibautomata.a *.d Затем пытаюсь подключить полученную библиотеку к Qt проекту, предварительно написав на C++:
В Qt проект добавил библиотеку собранную на D. При сборке проекта получаю ошибку:
Что-то ошибка совсем уж такая знакомая знакомая, но понять не могу, что не так. Подскажите пожалуйста. |
Автор: feodorv 12.7.2013, 14:23 |
А собственно тело функции createAutomata в библиотеке присутствует? |
Автор: Guinness 12.7.2013, 14:42 | ||||
feodorv, там вроде реализованно:
А может быть косяк в том, что произошло вот это объявление в С++ коде:
И данная функция перекрывает библиотечную? |
Автор: bsa 12.7.2013, 14:53 |
Guinness, если у них сигнатуры совпадают, то перекрытия быть не должно. Вопрос только в том, а как у D вообще с экспортом? Потому что даже экспорты разных компиляторов С++ несовместимы. |
Автор: volatile 12.7.2013, 14:56 |
Cкорей всего несоответствие компиляторов. В С++ есть такая весч как замангливание (mangled) имен функций. Так вот, соответствия в этом замангливании, нет даже в родном С++ коде от разных компиляторов. Что уж говорить об компиляторе D. Добавлено через 47 секунд упс. пост bsa, не видел |
Автор: feodorv 12.7.2013, 15:58 |
Вроде да, а с каким именем попало в библиотеку - неизвестно))) Вот))) Надо залезть внутрь библиотеки, поискать строчку createAutomata, и понять, что компилятор сотворил с именем. Быть может, там только лишний префикс по сравнению с именем, генерируемом в C++. |
Автор: AlterMann 12.7.2013, 19:44 | ||||||||
bsa, по идее, когда мы в D объявляем фукнцию как export(C++), компилятор кладёт в библиотеку функцию соответствующую правилам именования в С++. С другой стороны, куда уж там, если у каждого компилятора свои приколы могут быть в этом направлении. :( feodorv, посмотрел библиотеку и нашёл там пару вбросов такого содержания:
Правда мне это ни о чём не говорит. Попробовал скомпилировать D код с помощью GDC (на основе GCC 4.8.1). Опции компиляции и сборка библиотеки:
Библиотека собралась ок. При попытке собрать C++ проект - та же проблема. Посмотрел внутрь полученной библиотеки и обнаружил такое же вхождение упоминания о не линкуемой функции:
Пробовал менять сигнатуру функции в D коде с
безрезультатно. |
Автор: bsa 14.7.2013, 22:18 |
AlterMann, сделай тоже самое на С++ и посмотри, как будет в нем называться. |
Автор: AlterMann 15.7.2013, 11:12 | ||
Проблема сдвинулась с мёртвой точки. Внимательно посмотрев сигнатуру функции в скомпиленной библиотеке, я обнаружил не соответствие типов, и size_t или ulong преобразовывалось в unsigned long long, что явно не то же самое, что unsigned long. Чтобы раз и на всегда избавиться от этого, определил и в С++ и в D метод createAutomata(unsigned int, unsigned int), и вуаля, линковка этой функции таки прошла успешно. Но появились новые неожиданности. Теперь, в случае сборки библиотеки с помощью dmd (или gdc) и дальнейшей попытки заюзать библиотеку в C++ коде я получаю следующую ошибку:
Попробовал поставить перед классом CompleteAutomata квалификатор package, но это не дало результата. |
Автор: feodorv 15.7.2013, 12:30 |
На вид нужна какая-то D-библиотека... |
Автор: AlterMann 16.7.2013, 07:39 | ||||
Добавил, при сборке С++ проекта, флаг на включение стандартной библиотеки D phobos, причём для разных случаев компиляторов (dmd или gdc) свою соответствующую версию. Теперь, судя по всему, в случае dmd, недостаёт библиотеки libcurl-gnutils:
которую посмотрев интернет попробовал симулировать: ln -s /usr/lib64/libcurl.so.4 /usr/lib64/libcurl-gnutls.so.4 Но успехом это назвать нельзя, поскольку сообщение о недостатке libcurl-gnutls.so.4 пропадает, но остальные строки об undefined reference to остаются. Может надо откуда-то взять именно эту необыкновенную libcurl-gnutls? В случае gdc как-то по разному всякий раз происходит (что-то меняю, и уже не отдаю себе отчёта в том, что конкретно). Но достаточно часто проявляется ошибка multiple definition of, а также в конце о недостатке librt:
хотя в /usr/lib64 оно присутствует. Подскажите пожалуйста, куда дальше копать? ![]() В интернетах нашёл на эту тему лишь только пару гневных постов людей, которые восхищаются D, но продолжают писать на С++, и ругают создателя D (Уолтера Брайта) за то что якобы очень очень часто возникают подобные проблемы линковки. |
Автор: AlterMann 16.7.2013, 09:17 | ||
Для федоры не удалось сие найти, поэтому пришлось "симулировать". Фик знает. Мистика. ![]() Так обычно ругается, когда компилишь код на D, который не имеет main() функции. Но для библиотеки то куда эту main-функцию написать? И почему перед этой ошибкой и после неё проявляются сторонние страсти? Перешёл только для функции createAutomata, поскольку именно её использую в С++ проекте. Всё остальное остаётся в D библиотеке.
dmd из исходников собирать не пробовал, вместо этого скачивал RPM ну а дальше дело техники. Думаете стоит попробовать собрать? gdc нету прекомпиленных (не нашёл), поэтому собрал самостоятельно его. |
Автор: feodorv 16.7.2013, 17:25 | ||
Точно мистика))) Думаю, да, если есть время и желание. По крайней мере, странные зависимости от неуловимой libcurl-gnutls.so.4 должны пропасть... |
Автор: AlterMann 19.7.2013, 12:28 | ||||
Долго ли коротко ли, но до меня добрался тот самый мануал, в котором было написано как линковать D код с C++ кодом. Оказывается, в качестве линковщика нужно использовать тот же dmd, и в таком случае всё ок линукется и на выходе мы получаем вполне себе бинарничек. Правда в случае с Qt нужно подобавлять флагов линковки
чтобы были учтены Qt-шные либы. И радость моя была бы безграничной, если бы ещё полученный бинарничек таки заработал бы. Но вместо этого в момент запуска сразу же происходит Segmentation fault (core dumped). По сему печальному поводу gdb выдаёт не достаточно информативный бактрейс:
из которого можно судить о том, что траблы возникают в момент выделения памяти под объект в D коде. Стало быть как-то неправильно мои два кусочка работают друг с дружкою. И нельзя передавать чистый созданный D-объект в C++ код. Видимо нужно передачу такую осущесвлять в D коде, вызывая C++ функцию и передавая ей созданный объект. Но в таком случае это очень плохо, и подобные навороты мне противны. В случае с gdc линковка не удаётся - ругается на какие-то вызовы похожие на работу с тредами... |
Автор: AlterMann 23.7.2013, 00:11 |
Мне таки помог человек со stackoverflow. Оказалось, что в абстрактном C++ классе AutomataInterface не надо было прописывать виртуальный деструктор. А также, я в C++ коде удалял память по указателю на создаваемый в D коде объект. Ошибки вполне очевидные, если учитывать необходимость полного разделения управления памятью между линкуемыми компонентами. Сама линковка должна осущесвляться посредством dmd, причём main функция должна быть объявлена в D и вызывать C++ main функцию, которую предварительно нужно переименовать, например в maincpp. Код проекта доступен на гитхабе: https://github.com/newmen/d_life |
Автор: bsa 30.7.2013, 22:43 |
Это как?!? Может ты что-то не понял? Если у тебя есть виртуальные функции, то почему нельзя иметь виртуальный деструктор (ты про тело деструктора не забыл надеюсь)?!? |