![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
azure |
![]()
Сообщение
#1
|
Студент ![]() Группа: Участник Сообщений: 60 Регистрация: 24.12.2009 Пользователь №: 1332 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Вопрос не столько по кросплатформенности, сколько по Qt + .dll в винде. Имеется девайс (pci-карта gpib) с драйверами и .dll + .h с функциями работы с устройством. dll идут под MS Visual C++ и Borland C++ Builder. Можно ли использовать эти .dll без использования вышеуказанных компиляторов? Конкретно интересует gcc/mingw? Если можно, то как?
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#2
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(azure @ 22.4.2010, 15:52) Link Можно ли использовать эти .dll без использования вышеуказанных компиляторов? Конкретно интересует gcc/mingw? Если можно, то как? если dll создана по "всем правилам", то можно с помощью MinGW использовать dll'ку созданную MS Visual C++.Делается всё по аналогии со сборкой драйвера FireBird (QIBase). сделай pri-файл, для внешней библиотеки, положи его в её корень. Предположим, что заголовочник лежит в каталоге include lib-файл в каталоге lib и библиотека называется name.lib (name.dll, соответсвенно) тогда pri-файл должен выглядеть так
подключи этот pri-файл в свой файл проекта: include(path/to/lib.pri) |
|
|
azure |
![]()
Сообщение
#3
|
Студент ![]() Группа: Участник Сообщений: 60 Регистрация: 24.12.2009 Пользователь №: 1332 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Спасибо за подробные указания. Как узнать, сделана ли .dll "по всем правилам" или нет?
Я тут погуглил, люди говорят что длл бывают обычные и "расширенные". Обычные типа очень совместимые со всем, а расширенные имеют некую специализацию. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#4
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(azure @ 22.4.2010, 16:29) Link "по всем правилам" или нет? этого я и сам не знаю
|
|
|
Влад |
![]()
Сообщение
#5
|
Участник ![]() ![]() Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: ![]() ![]() ![]() |
Посмотри экспорты этой DLL (например, утилитой Depends.exe или любой другой).
Если в экспортах "простые читаемые" имена типа OpenDevice и т.п., то DLL скорее всего "простая", написанная по всем правилам. Если же в экспортах загадочные имена типа ??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ, то все совсем не так радужно ![]() |
|
|
Tonal |
![]()
Сообщение
#6
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Можно использовать dll-ку собранную одним компилятором в другом если она удовлетворяет следующему набору условий:
* dll-ка экспортирует чисто С-шные функции. * из неё не вылетает исключений. * структуры содержат только примитивные данные или другие такие же структуры. * структуры передаются только по указателям. * память, выделенная в dll-ки в ней же и освобождается. * dll-ка не пытается освободить память выделенную приложением. * не используются зависимые от компилятора соглашения о вызовах. * не используются зависимые от компиляторов расширения dll-ек (типа пакетов от багланда). Уф, вроде всё. ![]() Если какие-то из этих требований будут нарушены, то нужно смотреть по месту... Да, маленький бонус: полностью абстрактные структуры (интерфейсы) использовать можно. ![]() Сообщение отредактировал Tonal - 22.4.2010, 13:05 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#7
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Влад @ 22.4.2010, 17:00) Link Если в экспортах "простые читаемые" имена типа OpenDevice и т.п., Да к стати сейчас заглянул в fbclient_ms.dllи увидел чистенькие имена gds_describe ... А вот такой вопрос lib-файлы обязательны? Возможно ли линковка без них, если dll'ка простая? |
|
|
Iron Bug |
![]()
Сообщение
#8
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 22.4.2010, 16:40) Link А вот такой вопрос lib-файлы обязательны? Возможно ли линковка без них, если dll'ка простая? конечно. подгружаешь, линкуешь методы - и вперёд. собственно, это и есть динамическая загрузка библиотеки. нужны только имена точек входа. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#9
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
я имел в виду "возможно ли на этапе компиляции приложения использовать только dll'ки, без lib(a)-файлов. Как я понял MinGW (GCC) использует a-файлы (аналог lib-файлов) на этапе компиляции. Но обязательны ли они на этом этапе?
|
|
|
azure |
![]()
Сообщение
#10
|
Студент ![]() Группа: Участник Сообщений: 60 Регистрация: 24.12.2009 Пользователь №: 1332 Спасибо сказали: 5 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 22.4.2010, 15:49) Link я имел в виду "возможно ли на этапе компиляции приложения использовать только dll'ки, без lib(a)-файлов. Как я понял MinGW (GCC) использует a-файлы (аналог lib-файлов) на этапе компиляции. Но обязательны ли они на этом этапе? Хм! На виндовой машине с помощью gcc собирал либу qwt. Результат - .dll Далее собирается софтина, которая использует это qwt.dll В .pro добавлял LIBS += -lqwt5, в путь поиска библиотек добавлялась только .dll Мне не понятно, зачем вообще может быть нужен .lib (это же статическая либа, так ведь?) для линковки с динамической. И вообще, признаюсь честно, я плохо понимаю, как на самом деле вызываются функции из dll |
|
|
Litkevich Yuriy |
![]()
Сообщение
#11
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(azure @ 22.4.2010, 20:08) Link .lib (это же статическая либа, так ведь?) как я понял, в случае с GCC1) при создании статической библиотеки получается один большой a-файл 2) при создании динамической библиотеки получается один большой dll-файл и один крошечный a-файл (являющийся интерфейсом к dll) Но что это за интерфейс, насколько он обязателен, я не понял |
|
|
BRE |
![]()
Сообщение
#12
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 22.4.2010, 17:12) Link Но что это за интерфейс, насколько он обязателен, я не понял Если тебе не хочется загружать dll использую что-то типа QLibrary и самому резольвить имена функций, то можно прилинковать эту маленькую библиотеку и все будет происходить автоматически. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#13
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
ага, т.е. если у меня в распоряжении только dll'ка, то компиляция пройдёт успешно. Но прежде чем использовать содержимое dll'ки мне нужно будет воспользоваться классом QLibrary, так?
|
|
|
BRE |
![]()
Сообщение
#14
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 22.4.2010, 17:38) Link ага, т.е. если у меня в распоряжении только dll'ка, то компиляция пройдёт успешно. Но прежде чем использовать содержимое dll'ки мне нужно будет воспользоваться классом QLibrary, так? Да, ни при компиляции, ни при запуске программа не будет жестко связанна с этой dll, она будет как плагин. Но для доступа к ее функциям, необходимо будет ее загрузить и получить указатели на функции. |
|
|
Iron Bug |
![]()
Сообщение
#15
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
люди, у меня такое ощущение, что у вас в голове сильная каша по поводу lib(a), dll(so) и прочего такого. почитайте основы про статическую и динамическую линковку и про то, как системы их используют и для чего нужны эти файлы.
ну вот хотя бы тут почитайте (первый попавшийся ресурс на эту тему, из гугла): Link а то прям детсад, чесслово! |
|
|
BRE |
![]()
Сообщение
#16
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 22.4.2010, 21:23) Link а то прям детсад, чесслово! А мы про венду. ![]() |
|
|
Iron Bug |
![]()
Сообщение
#17
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(BRE @ 22.4.2010, 23:36) Link А мы про венду. ![]() ну дык то же самое. найдите такую же статью про венду. принципиальных отличий тут нет. а я так понимаю, что тут имеет место именно принципиальное непонимание использования разных типов линковки. |
|
|
BRE |
![]()
Сообщение
#18
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 22.4.2010, 21:43) Link принципиальных отличий тут нет. Разве. |
|
|
Iron Bug |
![]()
Сообщение
#19
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(BRE @ 22.4.2010, 23:48) Link Разве. с точностью до полной аналогии всех функций по работе с динамической загрузкой: загрузил, настроил линки на точки входа и работаешь с ними, потом выгрузил. у динамических библиотек есть спец функции для загрузки и выгрузки. плюс набор "рабочих" функций. что касается модулей, которые нужны для работы с ними - это только стандартные системно-зависимые библиотки по работе с динамическими библиотеками и сами динамические библиотеки. собственно, вот и всё. а что касается статики - так она просто жёстко линкуется к модулю юзера и тут никаких особенностей нет, собственно. работа как в случае с отдельными объектными модулями. lib делается из obj и принципиально они ничем не отличаются, кроме доп. описаний входов. P.S. правда, у линюкса чуть более гибкая система подгрузки динамических библиотек. можно управлять тем, как именно будут подгружаться библиотеки: сразу при вызове загрузки или только тогда, когда произойдёт явное обращение к входу из этой библиотеки. но это не меняет принципиальной схемы работы. Сообщение отредактировал Iron Bug - 22.4.2010, 21:47 |
|
|
BRE |
![]()
Сообщение
#20
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
венда/линукс под рукой есть?
Сделай небольшой пример и собери из него статическую библиотеку и динамическую библиотеку. Посмотри, какие файлы и какого размера при этому будут сгенерированы. Цитата P.S. правда, у линюкса чуть более гибкая система подгрузки динамических библиотек. можно управлять тем, как именно будут подгружаться библиотеки: сразу при вызове загрузки или только тогда, когда произойдёт явное обращение к входу из этой библиотеки. но это не меняет принципиальной схемы работы. А потом можно будет поговорить про ld.so и для чего вместе с .dll генерируется небольшой .lib (.a) файл. Сообщение отредактировал BRE - 22.4.2010, 21:55 |
|
|
Iron Bug |
![]()
Сообщение
#21
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
ну вот тебе кусок из реального проекта. весь не привожу - там дохрена и файлов, и вызовов. но не важно.
(тут libftdi - библиотека драйвера для одной микросхемы) Раскрывающийся текст
(тут много дополнительных мелких ухищрений: просто у меня уже есть стандартизированный подход к работе с разными библиотеками и мне так привычнее. но не суть.) вот это компилится без единого упоминания .a файла. линкуется с dl (ну там ещё rt и pthread, но это не существенно для примера). я и libftdi.а и libftdi.la убрала вообще из /usr/lib и больше их нет нигде и доступа к ним нет вообще - они под рута убраны. остались только libftdi.so файлы. однако, компилится и рекомпилится с нуля - будь здоров! потому что для работы с .so нужны только имена точек входа и имя самой .so библиотеки. и это у меня не один проект, а куча разных проектов, для разных девайсов. аналогично и под вендой на работе. там те же самые девайсы, те же библиотеки. и всё собирается без статики. такой же модуль под венду для этой железяки также динамически через вендозные функции грузит точки входа. я на память не вспомню как в венде вызываются загрузка и линковка входов, но всё совершенно аналогично. и .lib там тоже не нужен. Сообщение отредактировал Iron Bug - 22.4.2010, 23:43 |
|
|
BRE |
![]()
Сообщение
#22
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Мы говорим про венду! Посмотри внимательно, что какие файлы генерируются вместе с dll. dll нельзя слинковать с exe.
Сообщение отредактировал BRE - 23.4.2010, 6:30 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#23
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(BRE @ 23.4.2010, 10:29) Link dll нельзя слинковать с exe ты имеешь в виду статически?
|
|
|
BRE |
![]()
Сообщение
#24
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 23.4.2010, 9:27) Link ты имеешь в виду статически? Назовем это динамической линковкой. Например, так линкуются QtCore, QtGui, ... Мы не пишем код, который загружает эти библиотеки и настраивает адреса функций. Все это делает загрузчик, и если одной из dll не будет найдено, то еще до входа в main мы получим сообщение от загрузчика, что данная программа не может быть выполнена. В линукс линкер может работать напрямую с so-файлами, в венде же вместе с dll, генерируется небольшой файл lib (.a), который линкер использует при компоновке. Другой путь использовать dll, это загрузка его руками в своем коде, резольвинг необходимых функций и их использование. Для этого способа, этот файл lib (.a) не нужен, и программа будет запущенна даже если его нет (загрузчик про него ничего не знает и соответственно искать не будет). Это вариант для плагинов. |
|
|
Tonal |
![]()
Сообщение
#25
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
В винде не все линкеры умеют пользоваться символами напрямую из dll-ки.
Например MSVC не умел - сейчас не знаю. Старый mingw не умел - сейчас научили. Кроме того он понимает импортные либки от MSVC. Багланд - не помню, вроде умеет. ![]() Причём обычно библиотеки импорта (т. е. либки, которые для линковки с dll-ками) действительно содержат только перечень экспортируемых символов, что делает их довольно бессмысленными и легко конвертируемыми между разными форматами. ![]() Но несколько раз мне встречались импортные либки, которые содержали ещё что-то, т. е. конвертировать их не удавалось... |
|
|
Iron Bug |
![]()
Сообщение
#26
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(BRE @ 23.4.2010, 9:29) Link Мы говорим про венду! Посмотри внимательно, что какие файлы генерируются вместе с dll. dll нельзя слинковать с exe. ..ять! я уже три раза сказала, что разницы нет. под вендой и линём это совершенно одинаковые схемы. это не линковка, а динамическая загрузка. разные вещи. я десять лет пишу такие проги, а ты мне тут говоришь, что нельзя ![]() точно так же - LoadLibrary и вперёд с песнями. и не нужно там ничего больше, кроме загрузки и линковки входов. а как ваша QT устроена - этого я не знаю и это частные проблемы этой библиотеки. скорее всего, и её можно также грузить. просто для упрощения придумали автозагрузку и какую-нибудь инициализацию в виде статически линкующегося к коду куска. вот кусок из работающего проекта, который знать не знает про lib'ы, линкует только стандартные библиотеки и прекрасно живёт, подключаясь к Ftd2xx.dll: Раскрывающийся текст
совершенно та же фигня. только dlopen заменён на LoadLibrary, а dlsym на GetProcAddress. ну выгрузка библиотеки в обоих примерах пропущена, но она такая же аналогичная. Сообщение отредактировал Iron Bug - 23.4.2010, 11:59 |
|
|
BRE |
![]()
Сообщение
#27
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Iron Bug, ты все динамические библиотеки загружаешь руками с помощью LoadLibrary и получаешь адреса их функций? Или все таки есть такие, которые "кто-то" загружает за тебя (например msvcrt.dll)? А как происходит процесс линковки таких библиотек?
Раньше все, сейчас (как сообщих Tonal) некоторые, линкеры использовали для этого специальную библиотеку импорта... Ну вроде все это уже несколько раз описано выше, не буду повторяться. ![]() То, что ты не замечаешь как происходит этот процесс заслуга компилятора. Кстати, каким пользуешься? |
|
|
Iron Bug |
![]()
Сообщение
#28
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(BRE @ 23.4.2010, 15:21) Link Iron Bug, ты все динамические библиотеки загружаешь руками с помощью LoadLibrary и получаешь адреса их функций? Или все таки есть такие, которые "кто-то" загружает за тебя (например msvcrt.dll)? А как происходит процесс линковки таких библиотек? msvcrt загружает только основной модуль. он прикрепляет к юзерскому коду заголовок для загрузчика и прописывает основную точку входа(но и это можно сделать вручную, если нужно). остальные загрузки по ходу работы - см. приведённый код. динамическая загрузка вызовом LoadLibrary(она вызывается из Kernel32.dll), по которому в системе происходит загрузка библиотеки в память и вызов внутреннего метода библиотеки init (под вендой название точно не помню, но если сам пишешь dll, которой нужна инициализация - то его надо писать вручную, а если нет - то компилятор по типу собираемого модуля dll сам его прилепит, сгенерировав по умолчанию). после вызова этой функции и линковки точек входа библиотека готова к работе. и неважно, каким компилятором она собрала. если имена точек входа указаны без декораций(а для этого прописывается файл экспорта при сборке библиотеки), то это работает. и даже если пересобрать библиотеку, добавить что-то, то ничего не изменится, пока указанные имена входов и их параметры остались теми же. производители аппаратуры так и делают, чтобы расширять свои библиотеки для новых версий. потому что иначе после каждого апдейта зависимый код пришлось бы перекомпилять из-за линковки по номерам входов. а так, один раз написал, отправил юзеру и пускай он себе обновляет дрова - для модуля ничего не изменится, пока интерфейс совместим. Сообщение отредактировал Iron Bug - 23.4.2010, 13:56 |
|
|
BRE |
![]()
Сообщение
#29
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 23.4.2010, 14:52) Link и неважно, каким компилятором она собрала. если имена точек входа указаны без декораций(а для этого прописывается файл экспорта при сборке библиотеки), то это работает. и даже если пересобрать библиотеку, добавить что-то, то ничего не изменится, пока указанные имена входов и их параметры остались теми же. производители аппаратуры так и делают, чтобы расширять свои библиотеки для новых версий. потому что иначе после каждого апдейта зависимый код пришлось бы перекомпилять из-за линковки по номерам входов. а так, один раз написал, отправил юзеру и пускай он себе обновляет дрова - для модуля ничего не изменится, пока интерфейс совместим. Да это все понятно, никто и не говорит обратного. Это базовые понятия про разделяемые библиотеки... Вот ключевой момент: Цитата(Iron Bug @ 23.4.2010, 14:52) Link msvcrt загружает только основной модуль. он прикрепляет к юзерскому коду заголовок для загрузчика и прописывает основную точку входа(но и это можно сделать вручную, если нужно). А кто прикрепляет к юзерскому коду заголовок (а точнее таблицу импорта)? И откуда эта таблица берется? ![]() А делает это линкеры, и по крайней, мере большей их части нужна для этого библиотека импорта. При старте процесса, еще до передачи управления в функцию _main, загрузчик загружает dll используя LoadLibrary, резолвит нужные функции и уже в памяти настраивает эти таблицы импорта для процесса. |
|
|
Iron Bug |
![]()
Сообщение
#30
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(BRE @ 23.4.2010, 17:07) Link А кто прикрепляет к юзерскому коду заголовок (а точнее таблицу импорта)? И откуда эта таблица берется? см. код. когда ты линкуешь метод, вызывая GetProcAddress - система просматривает внутреннюю таблицу экспорта dll и, если находит метод с запрашиваемым именем, то подгружает его. имя это ты можешь выбирать вообще динамически. то есть, ты можешь написать программу для выполнения любого метода любой библиотеки, задавая их через юзерский интерфейс. и никакие lib'ы и статическая информация тут не нужны. в этом случае на этапе компиляции и линковки никаких предположений об адресе функции не делается вообще. я знаю, что именно ты путаешь с динамической загрузкой. есть т.н. динамическая линковка. но это линковка по номерам входов. загрузка библиотеки происходит при загрузке основного модуля (msvcrt генерит автоматический код) и в модуле буквально прописываются связи типа "вызов метода номер 2 из библиотеки такой-то". и вот именно для этого и нужны эти самые таблицы импорта. но это не универсальный метод, в том смысле, что при существенных изменениях в библиотеке номера входов могут меняться и тогда кердык всем зависящим от этих номеров приложениям. при этом при смещении номеров происходит вызов не той функции (причём система не проверяет этого) и программа чаще всего просто падает с access voilation. мелкософт обозвали это явление hell dll и начали городить огород с системой хранения версий в весьма дурацком стиле. а в линюксе для этого изначально были методы (приписывание версии к названию .so библиотеки). кроме этого, есть ещё гарантированно работающая статическая линковка, понятное дело. так что таблицы экспорта - это полумера и она работает в весьма ограниченном диапазоне, хотя и куда легче в реализации, потому что компилятор сам всё делает за программиста. Сообщение отредактировал Iron Bug - 23.4.2010, 14:29 |
|
|
BRE |
![]()
Сообщение
#31
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 23.4.2010, 15:29) Link я знаю, что именно ты путаешь с динамической загрузкой. есть т.н. динамическая линковка. Я путаю? Перечитай мои посты, по-моему это ты путаешь. ![]() Я тут про динамическую линковку и распинаюсь, а ты мне какие-то базовые понятия про разделяемые библиотеки пишешь. ![]() Цитата(Iron Bug @ 23.4.2010, 15:29) Link но это линковка по номерам входов. загрузка библиотеки происходит при загрузке основного модуля (msvcrt генерит автоматический код) Ни msvcrt.dll, ни kernel32.dll, ни какая другая dll ничего генерить уже не может, генерть может линкер, основываясь на этих самых библиотеках импорта или новые линкеры, которые по сути сами формируют таблицу импорта без генерации этих библиотек. Цитата(Iron Bug @ 23.4.2010, 15:29) Link но это не универсальный метод, в том смысле, что при существенных изменениях в библиотеке номера входов могут меняться и тогда кердык всем зависящим от этих номеров приложениям. Мы говорим не о плюсах/минусах, а о том как это происходит и почему/зачем вместе с dll генерируется файл .lib (.a). Фух. ![]() Сообщение отредактировал BRE - 23.4.2010, 14:48 |
|
|
Iron Bug |
![]()
Сообщение
#32
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
я вообще-то изначально отвечала на исходный вопрос.
Цитата(azure @ 22.4.2010, 14:52) Link Имеется девайс (pci-карта gpib) с драйверами и .dll + .h с функциями работы с устройством. dll идут под MS Visual C++ и Borland C++ Builder. Можно ли использовать эти .dll без использования вышеуказанных компиляторов? Конкретно интересует gcc/mingw? Если можно, то как? так как были даны неверные ответы про необходимость lib'ов, я ответила, что да, можно. и привела примеры. у меня интелловский компилятор вполне нормально общается с любыми dll под венду, при этом для работы требуются только заголовочники и сама dll. Цитата(BRE @ 23.4.2010, 17:46) Link Ни msvcrt.dll, ни kernel32.dll, ни какая другая dll ничего генерить уже не может, генерть может линкер, основываясь на этих самых библиотеках импорта или новые линкеры, которые по сути сами формируют таблицу импорта без генерации этих библиотек. ну тут я просто неточно выразилась. на самом деле, линкер тащит прототип загрузчика из msvcrt и прилепляет его к модулю. а в kernel32 хранится та самая функция, которая загружает динамически библиотеку при вызове LoadLibrary и выполняет динамическую линковку точек входа при выполнении программы. я не буду спорить. если хочется зависимости от версии драйвера - делайте как хотите. линкуйте через таблицы импорта. дело ваше. я пояснила, в чём вред такого метода. по-моему, написать пару лишних строк кода и отделаться от перекомпиляции приложения под каждую новую dll от производителя дров - не такая уж плохая идея. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#33
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Тему разделил: Link
|
|
|
Tonal |
![]()
Сообщение
#34
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 23.4.2010, 21:57) Link ну тут я просто неточно выразилась. на самом деле, линкер тащит прототип загрузчика из msvcrt и прилепляет его к модулю. а в kernel32 хранится та самая функция, которая загружает динамически библиотеку при вызове LoadLibrary и выполняет динамическую линковку точек входа при выполнении программы. И опять ты не точно выразилась. ![]() msvcrt - это Microsoft C Runtime Libraryю там сидят функции рантайма типа fopen и abort. А к модулю прицепляется стартовая функция, которая потом вызывает main, или, если модуль собирается в dll-ку, то DllEntryPoint. Эти стартовые функции свои для каждого компилятора и живут в статических библиотеках. Цитата(Iron Bug @ 23.4.2010, 21:57) Link я не буду спорить. если хочется зависимости от версии драйвера - делайте как хотите. линкуйте через таблицы импорта. дело ваше. я пояснила, в чём вред такого метода. по-моему, написать пару лишних строк кода и отделаться от перекомпиляции приложения под каждую новую dll от производителя дров - не такая уж плохая идея. Динамическая линковка возможна как по ординалам, так и по именам. По именам - по умолчанию, если есть и то и другое. Т. е. перелинковывать приложение при изменении dll-ки требуется только в том случае, если изменились имена и/или сигнатуры. Но в этом случае тебе всё равно придётся не только перелинковывать, но корректировать текст вызова и перекомпилять приложение. Фича динамической линковки в том, что если при старте все указанные dll-ки подгружаются и их импорты разрешаются (резольвятся). И при обломе приложение не стартует. Явный минус в том, что на это тратится время и память на старте и dll-ка постоянно висит в памяти, даже в случае, когда она нужна только какой-нибудь редкой и экзотической функции. Когда это становится критичным, например с плагинами, применяют динамическую загрузку. Да, в винде есть ещё механизм отложенной загрузки - когда dll-ка подгружается системой не при старте а при первом обращении. Перечитай Джеффри Рихтер-а "Windows для профессионалов" - там очень подробно описано про динамическую линковку. ![]() |
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 15.8.2025, 5:08 |