Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Использование сторонних библиотек
Форум на CrossPlatform.RU > Библиотеки > Другие библиотеки
azure
Вопрос не столько по кросплатформенности, сколько по Qt + .dll в винде. Имеется девайс (pci-карта gpib) с драйверами и .dll + .h с функциями работы с устройством. dll идут под MS Visual C++ и Borland C++ Builder. Можно ли использовать эти .dll без использования вышеуказанных компиляторов? Конкретно интересует gcc/mingw? Если можно, то как?
Litkevich Yuriy
Цитата(azure @ 22.4.2010, 15:52) *
Можно ли использовать эти .dll без использования вышеуказанных компиляторов? Конкретно интересует gcc/mingw? Если можно, то как?
если dll создана по "всем правилам", то можно с помощью MinGW использовать dll'ку созданную MS Visual C++.

Делается всё по аналогии со сборкой драйвера FireBird (QIBase).



сделай pri-файл, для внешней библиотеки, положи его в её корень.
Предположим, что заголовочник лежит в каталоге include
lib-файл в каталоге lib
и библиотека называется name.lib (name.dll, соответсвенно)
тогда pri-файл должен выглядеть так
INCLUDEPATH +=    $$PWD/include
QMAKE_LIBDIR += $$PWD/lib
LIBS += -lname

подключи этот pri-файл в свой файл проекта:
include(path/to/lib.pri)
azure
Спасибо за подробные указания. Как узнать, сделана ли .dll "по всем правилам" или нет?
Я тут погуглил, люди говорят что длл бывают обычные и "расширенные". Обычные типа очень совместимые со всем, а расширенные имеют некую специализацию.
Litkevich Yuriy
Цитата(azure @ 22.4.2010, 16:29) *
"по всем правилам" или нет?
этого я и сам не знаю
Влад
Посмотри экспорты этой DLL (например, утилитой Depends.exe или любой другой).
Если в экспортах "простые читаемые" имена типа OpenDevice и т.п., то DLL скорее всего "простая", написанная по всем правилам.
Если же в экспортах загадочные имена типа ??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ, то все совсем не так радужно :) - другой компилятор такую DLL скорее всего не поймет; а если и поймет, то не факт, что сможет с ней правильно работать.
Tonal
Можно использовать dll-ку собранную одним компилятором в другом если она удовлетворяет следующему набору условий:
* dll-ка экспортирует чисто С-шные функции.
* из неё не вылетает исключений.
* структуры содержат только примитивные данные или другие такие же структуры.
* структуры передаются только по указателям.
* память, выделенная в dll-ки в ней же и освобождается.
* dll-ка не пытается освободить память выделенную приложением.
* не используются зависимые от компилятора соглашения о вызовах.
* не используются зависимые от компиляторов расширения dll-ек (типа пакетов от багланда).
Уф, вроде всё. :)

Если какие-то из этих требований будут нарушены, то нужно смотреть по месту...

Да, маленький бонус: полностью абстрактные структуры (интерфейсы) использовать можно. :)
Litkevich Yuriy
Цитата(Влад @ 22.4.2010, 17:00) *
Если в экспортах "простые читаемые" имена типа OpenDevice и т.п.,
Да к стати сейчас заглянул в fbclient_ms.dll
и увидел чистенькие имена gds_describe ...
Нажмите для просмотра прикрепленного файла

А вот такой вопрос lib-файлы обязательны? Возможно ли линковка без них, если dll'ка простая?
Iron Bug
Цитата(Litkevich Yuriy @ 22.4.2010, 16:40) *
А вот такой вопрос lib-файлы обязательны? Возможно ли линковка без них, если dll'ка простая?

конечно. подгружаешь, линкуешь методы - и вперёд. собственно, это и есть динамическая загрузка библиотеки. нужны только имена точек входа.
Litkevich Yuriy
я имел в виду "возможно ли на этапе компиляции приложения использовать только dll'ки, без lib(a)-файлов. Как я понял MinGW (GCC) использует a-файлы (аналог lib-файлов) на этапе компиляции. Но обязательны ли они на этом этапе?
azure
Цитата(Litkevich Yuriy @ 22.4.2010, 15:49) *
я имел в виду "возможно ли на этапе компиляции приложения использовать только dll'ки, без lib(a)-файлов. Как я понял MinGW (GCC) использует a-файлы (аналог lib-файлов) на этапе компиляции. Но обязательны ли они на этом этапе?


Хм! На виндовой машине с помощью gcc собирал либу qwt. Результат - .dll
Далее собирается софтина, которая использует это qwt.dll
В .pro добавлял LIBS += -lqwt5, в путь поиска библиотек добавлялась только .dll

Мне не понятно, зачем вообще может быть нужен .lib (это же статическая либа, так ведь?) для линковки с динамической. И вообще, признаюсь честно, я плохо понимаю, как на самом деле вызываются функции из dll
Litkevich Yuriy
Цитата(azure @ 22.4.2010, 20:08) *
.lib (это же статическая либа, так ведь?)
как я понял, в случае с GCC
1) при создании статической библиотеки получается один большой a-файл
2) при создании динамической библиотеки получается один большой dll-файл и один крошечный a-файл (являющийся интерфейсом к dll)

Но что это за интерфейс, насколько он обязателен, я не понял
BRE
Цитата(Litkevich Yuriy @ 22.4.2010, 17:12) *
Но что это за интерфейс, насколько он обязателен, я не понял

Если тебе не хочется загружать dll использую что-то типа QLibrary и самому резольвить имена функций, то можно прилинковать эту маленькую библиотеку и все будет происходить автоматически.
Litkevich Yuriy
ага, т.е. если у меня в распоряжении только dll'ка, то компиляция пройдёт успешно. Но прежде чем использовать содержимое dll'ки мне нужно будет воспользоваться классом QLibrary, так?
BRE
Цитата(Litkevich Yuriy @ 22.4.2010, 17:38) *
ага, т.е. если у меня в распоряжении только dll'ка, то компиляция пройдёт успешно. Но прежде чем использовать содержимое dll'ки мне нужно будет воспользоваться классом QLibrary, так?

Да, ни при компиляции, ни при запуске программа не будет жестко связанна с этой dll, она будет как плагин. Но для доступа к ее функциям, необходимо будет ее загрузить и получить указатели на функции.
Iron Bug
люди, у меня такое ощущение, что у вас в голове сильная каша по поводу lib(a), dll(so) и прочего такого. почитайте основы про статическую и динамическую линковку и про то, как системы их используют и для чего нужны эти файлы.

ну вот хотя бы тут почитайте (первый попавшийся ресурс на эту тему, из гугла):

http://www.yolinux.com/TUTORIALS/LibraryAr...AndDynamic.html

а то прям детсад, чесслово!
BRE
Цитата(Iron Bug @ 22.4.2010, 21:23) *
а то прям детсад, чесслово!

А мы про венду. ;)
Iron Bug
Цитата(BRE @ 22.4.2010, 23:36) *
А мы про венду. ;)

ну дык то же самое. найдите такую же статью про венду. принципиальных отличий тут нет. а я так понимаю, что тут имеет место именно принципиальное непонимание использования разных типов линковки.
BRE
Цитата(Iron Bug @ 22.4.2010, 21:43) *
принципиальных отличий тут нет.

Разве.
Iron Bug
Цитата(BRE @ 22.4.2010, 23:48) *
Разве.

с точностью до полной аналогии всех функций по работе с динамической загрузкой: загрузил, настроил линки на точки входа и работаешь с ними, потом выгрузил. у динамических библиотек есть спец функции для загрузки и выгрузки. плюс набор "рабочих" функций. что касается модулей, которые нужны для работы с ними - это только стандартные системно-зависимые библиотки по работе с динамическими библиотеками и сами динамические библиотеки. собственно, вот и всё.
а что касается статики - так она просто жёстко линкуется к модулю юзера и тут никаких особенностей нет, собственно. работа как в случае с отдельными объектными модулями. lib делается из obj и принципиально они ничем не отличаются, кроме доп. описаний входов.

P.S. правда, у линюкса чуть более гибкая система подгрузки динамических библиотек. можно управлять тем, как именно будут подгружаться библиотеки: сразу при вызове загрузки или только тогда, когда произойдёт явное обращение к входу из этой библиотеки. но это не меняет принципиальной схемы работы.
BRE
венда/линукс под рукой есть?
Сделай небольшой пример и собери из него статическую библиотеку и динамическую библиотеку. Посмотри, какие файлы и какого размера при этому будут сгенерированы.

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

А потом можно будет поговорить про ld.so и для чего вместе с .dll генерируется небольшой .lib (.a) файл.
Iron Bug
ну вот тебе кусок из реального проекта. весь не привожу - там дохрена и файлов, и вызовов. но не важно.
(тут libftdi - библиотека драйвера для одной микросхемы)
Раскрывающийся текст

#include <dlfcn.h>


using namespace std;

typedef void* dll_handle_t;

typedef int (*ftdi_init_func_t)(struct ftdi_context *); // определения типов для точек входа библиотеки
...........
typedef void (*ftdi_deinit_func_t)(struct ftdi_context *);
class ftdidev_c
{
    public:
        ftdidev_c();
        ~ftdidev_c();

    protected:
        static dll_handle_t _dll;
        struct ftdi_context _ftdic;

        ftdi_init_func_t            pinit;   //་ указатели на функции, к которым динамически линкуются входы библиотеки
.....................
        ftdi_deinit_func_t          pdeinit;
    public:
        bool all_func_ok();
        int init();  // обёртка для вызова указателя на функцию
.........
        int deinit();
};


dll_handle_t ftdidev_c::_dll = dlopen("libftdi.so",RTLD_LAZY); // открытие хэндла библиотеки (без загрузки)

ftdidev_c::ftdidev_c()
{
    if(_dll != NULL)
    {
        pinit = (ftdi_init_func_t)dlsym(_dll,"ftdi_init");  // динамическая линковка точек в библиотеке к определённым внутри класса указателям на функции
.................................
        pdeinit = (ftdi_deinit_func_t)dlsym(_dll,"ftdi_deinit");
    }
    if(pinit != NULL)
    {
        (*pinit)(&_ftdic);
    }
}

ftdidev_c::~ftdidev_c()
{
    if(pdeinit != NULL)
    {
        (*pdeinit)(&_ftdic);
    }
}

bool ftdidev_c::all_func_ok()
{
    if(pinit == NULL) return false;
........................
    if(pdeinit == NULL) return false;
    return true;
}

int ftdidev_c::init()  // реализация обёртки для вызова указателя на функцию
{а на работе у меня
    if(pinit != NULL)
    {
        return (*pinit)(&_ftdic);
    }
    return FTDI_ERR_DLL_FUNC_UNDEFINED;
}


int ftdidev_c::deinit()
{
    if(pdeinit != NULL)
    {
        (*pdeinit)(&_ftdic);
        return FTDI_FUNC_OK;
    }
    return FTDI_ERR_DLL_FUNC_UNDEFINED;
}


(тут много дополнительных мелких ухищрений: просто у меня уже есть стандартизированный подход к работе с разными библиотеками и мне так привычнее. но не суть.)
вот это компилится без единого упоминания .a файла. линкуется с dl (ну там ещё rt и pthread, но это не существенно для примера).
я и libftdi.а и libftdi.la убрала вообще из /usr/lib и больше их нет нигде и доступа к ним нет вообще - они под рута убраны. остались только libftdi.so файлы.
однако, компилится и рекомпилится с нуля - будь здоров! потому что для работы с .so нужны только имена точек входа и имя самой .so библиотеки.

и это у меня не один проект, а куча разных проектов, для разных девайсов. аналогично и под вендой на работе. там те же самые девайсы, те же библиотеки. и всё собирается без статики.
такой же модуль под венду для этой железяки также динамически через вендозные функции грузит точки входа. я на память не вспомню как в венде вызываются загрузка и линковка входов, но всё совершенно аналогично. и .lib там тоже не нужен.
BRE
Мы говорим про венду! Посмотри внимательно, что какие файлы генерируются вместе с dll. dll нельзя слинковать с exe.
Litkevich Yuriy
Цитата(BRE @ 23.4.2010, 10:29) *
dll нельзя слинковать с exe
ты имеешь в виду статически?
BRE
Цитата(Litkevich Yuriy @ 23.4.2010, 9:27) *
ты имеешь в виду статически?

Назовем это динамической линковкой.
Например, так линкуются QtCore, QtGui, ...
Мы не пишем код, который загружает эти библиотеки и настраивает адреса функций. Все это делает загрузчик, и если одной из dll не будет найдено, то еще до входа в main мы получим сообщение от загрузчика, что данная программа не может быть выполнена.
В линукс линкер может работать напрямую с so-файлами, в венде же вместе с dll, генерируется небольшой файл lib (.a), который линкер использует при компоновке.

Другой путь использовать dll, это загрузка его руками в своем коде, резольвинг необходимых функций и их использование. Для этого способа, этот файл lib (.a) не нужен, и программа будет запущенна даже если его нет (загрузчик про него ничего не знает и соответственно искать не будет). Это вариант для плагинов.
Tonal
В винде не все линкеры умеют пользоваться символами напрямую из dll-ки.

Например MSVC не умел - сейчас не знаю.
Старый mingw не умел - сейчас научили. Кроме того он понимает импортные либки от MSVC.
Багланд - не помню, вроде умеет. :)

Причём обычно библиотеки импорта (т. е. либки, которые для линковки с dll-ками) действительно содержат только перечень экспортируемых символов, что делает их довольно бессмысленными и легко конвертируемыми между разными форматами. :)
Но несколько раз мне встречались импортные либки, которые содержали ещё что-то, т. е. конвертировать их не удавалось...
Iron Bug
Цитата(BRE @ 23.4.2010, 9:29) *
Мы говорим про венду! Посмотри внимательно, что какие файлы генерируются вместе с dll. dll нельзя слинковать с exe.

..ять! я уже три раза сказала, что разницы нет. под вендой и линём это совершенно одинаковые схемы. это не линковка, а динамическая загрузка. разные вещи.
я десять лет пишу такие проги, а ты мне тут говоришь, что нельзя :) каждый день я загружаю десятки разных сторонних библиотек для железа и всё нормально. а ты сейчас доказываешь мне, что все десять лет у меня ничего не работало.
точно так же - LoadLibrary и вперёд с песнями. и не нужно там ничего больше, кроме загрузки и линковки входов.
а как ваша QT устроена - этого я не знаю и это частные проблемы этой библиотеки. скорее всего, и её можно также грузить. просто для упрощения придумали автозагрузку и какую-нибудь инициализацию в виде статически линкующегося к коду куска.
вот кусок из работающего проекта, который знать не знает про lib'ы, линкует только стандартные библиотеки и прекрасно живёт, подключаясь к Ftd2xx.dll:
Раскрывающийся текст
class cFtdiDrv
{
.................
    HMODULE     fthmodule;

    FT_STATUS   ftLoadDLL(void);  

    typedef FT_STATUS (WINAPI *PtrToOpen)(PVOID, FT_HANDLE *);  // определение типа функции (точки входа)
    PtrToOpen pFtOpen; // указатель на функцию для подключения входа

    FT_STATUS ftOpen(PVOID); // обёртка для вызова прилинкованного указателя
................
}

FT_STATUS  cFtdiDrv::ftLoadDLL()
{
    fthmodule = LoadLibrary("Ftd2xx.dll");                          // загрузка Dll по имени
    if(fthmodule == NULL)
    {
         return FT_INVALID_HANDLE;
    }

    pFtOpen = (PtrToOpen)GetProcAddress(fthmodule, "FT_Open");    // подключение указателя к входу библиотеки по имени функции
    if (pFtOpen == NULL)
    {
        return FT_INVALID_HANDLE;
    }
.....
}

FT_STATUS cFtdiDrv::ftOpen(PVOID pvDevice)
{
    if (!pFtOpen)
    {
        return FT_INVALID_HANDLE;
    }
    return (*pFtOpen)(pvDevice, &ftHandle ); // вызов прилинкованной функции через указатель
}

совершенно та же фигня. только dlopen заменён на LoadLibrary, а dlsym на GetProcAddress. ну выгрузка библиотеки в обоих примерах пропущена, но она такая же аналогичная.
BRE
Iron Bug, ты все динамические библиотеки загружаешь руками с помощью LoadLibrary и получаешь адреса их функций? Или все таки есть такие, которые "кто-то" загружает за тебя (например msvcrt.dll)? А как происходит процесс линковки таких библиотек?

Раньше все, сейчас (как сообщих Tonal) некоторые, линкеры использовали для этого специальную библиотеку импорта... Ну вроде все это уже несколько раз описано выше, не буду повторяться. :)
То, что ты не замечаешь как происходит этот процесс заслуга компилятора. Кстати, каким пользуешься?
Iron Bug
Цитата(BRE @ 23.4.2010, 15:21) *
Iron Bug, ты все динамические библиотеки загружаешь руками с помощью LoadLibrary и получаешь адреса их функций? Или все таки есть такие, которые "кто-то" загружает за тебя (например msvcrt.dll)? А как происходит процесс линковки таких библиотек?

msvcrt загружает только основной модуль. он прикрепляет к юзерскому коду заголовок для загрузчика и прописывает основную точку входа(но и это можно сделать вручную, если нужно). остальные загрузки по ходу работы - см. приведённый код. динамическая загрузка вызовом LoadLibrary(она вызывается из Kernel32.dll), по которому в системе происходит загрузка библиотеки в память и вызов внутреннего метода библиотеки init (под вендой название точно не помню, но если сам пишешь dll, которой нужна инициализация - то его надо писать вручную, а если нет - то компилятор по типу собираемого модуля dll сам его прилепит, сгенерировав по умолчанию). после вызова этой функции и линковки точек входа библиотека готова к работе. и неважно, каким компилятором она собрала. если имена точек входа указаны без декораций(а для этого прописывается файл экспорта при сборке библиотеки), то это работает. и даже если пересобрать библиотеку, добавить что-то, то ничего не изменится, пока указанные имена входов и их параметры остались теми же.
производители аппаратуры так и делают, чтобы расширять свои библиотеки для новых версий. потому что иначе после каждого апдейта зависимый код пришлось бы перекомпилять из-за линковки по номерам входов. а так, один раз написал, отправил юзеру и пускай он себе обновляет дрова - для модуля ничего не изменится, пока интерфейс совместим.
BRE
Цитата(Iron Bug @ 23.4.2010, 14:52) *
и неважно, каким компилятором она собрала. если имена точек входа указаны без декораций(а для этого прописывается файл экспорта при сборке библиотеки), то это работает. и даже если пересобрать библиотеку, добавить что-то, то ничего не изменится, пока указанные имена входов и их параметры остались теми же.
производители аппаратуры так и делают, чтобы расширять свои библиотеки для новых версий. потому что иначе после каждого апдейта зависимый код пришлось бы перекомпилять из-за линковки по номерам входов. а так, один раз написал, отправил юзеру и пускай он себе обновляет дрова - для модуля ничего не изменится, пока интерфейс совместим.

Да это все понятно, никто и не говорит обратного. Это базовые понятия про разделяемые библиотеки...

Вот ключевой момент:
Цитата(Iron Bug @ 23.4.2010, 14:52) *
msvcrt загружает только основной модуль. он прикрепляет к юзерскому коду заголовок для загрузчика и прописывает основную точку входа(но и это можно сделать вручную, если нужно).

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

При старте процесса, еще до передачи управления в функцию _main, загрузчик загружает dll используя LoadLibrary, резолвит нужные функции и уже в памяти настраивает эти таблицы импорта для процесса.
Iron Bug
Цитата(BRE @ 23.4.2010, 17:07) *
А кто прикрепляет к юзерскому коду заголовок (а точнее таблицу импорта)? И откуда эта таблица берется?

см. код. когда ты линкуешь метод, вызывая GetProcAddress - система просматривает внутреннюю таблицу экспорта dll и, если находит метод с запрашиваемым именем, то подгружает его. имя это ты можешь выбирать вообще динамически. то есть, ты можешь написать программу для выполнения любого метода любой библиотеки, задавая их через юзерский интерфейс. и никакие lib'ы и статическая информация тут не нужны. в этом случае на этапе компиляции и линковки никаких предположений об адресе функции не делается вообще.
я знаю, что именно ты путаешь с динамической загрузкой. есть т.н. динамическая линковка. но это линковка по номерам входов. загрузка библиотеки происходит при загрузке основного модуля (msvcrt генерит автоматический код) и в модуле буквально прописываются связи типа "вызов метода номер 2 из библиотеки такой-то". и вот именно для этого и нужны эти самые таблицы импорта. но это не универсальный метод, в том смысле, что при существенных изменениях в библиотеке номера входов могут меняться и тогда кердык всем зависящим от этих номеров приложениям. при этом при смещении номеров происходит вызов не той функции (причём система не проверяет этого) и программа чаще всего просто падает с access voilation. мелкософт обозвали это явление hell dll и начали городить огород с системой хранения версий в весьма дурацком стиле. а в линюксе для этого изначально были методы (приписывание версии к названию .so библиотеки).
кроме этого, есть ещё гарантированно работающая статическая линковка, понятное дело.

так что таблицы экспорта - это полумера и она работает в весьма ограниченном диапазоне, хотя и куда легче в реализации, потому что компилятор сам всё делает за программиста.
BRE
Цитата(Iron Bug @ 23.4.2010, 15:29) *
я знаю, что именно ты путаешь с динамической загрузкой. есть т.н. динамическая линковка.

Я путаю? Перечитай мои посты, по-моему это ты путаешь. ;)
Я тут про динамическую линковку и распинаюсь, а ты мне какие-то базовые понятия про разделяемые библиотеки пишешь. :)

Цитата(Iron Bug @ 23.4.2010, 15:29) *
но это линковка по номерам входов. загрузка библиотеки происходит при загрузке основного модуля (msvcrt генерит автоматический код)

Ни msvcrt.dll, ни kernel32.dll, ни какая другая dll ничего генерить уже не может, генерть может линкер, основываясь на этих самых библиотеках импорта или новые линкеры, которые по сути сами формируют таблицу импорта без генерации этих библиотек.

Цитата(Iron Bug @ 23.4.2010, 15:29) *
но это не универсальный метод, в том смысле, что при существенных изменениях в библиотеке номера входов могут меняться и тогда кердык всем зависящим от этих номеров приложениям.

Мы говорим не о плюсах/минусах, а о том как это происходит и почему/зачем вместе с dll генерируется файл .lib (.a).

Фух. :)
Iron Bug
я вообще-то изначально отвечала на исходный вопрос.
Цитата(azure @ 22.4.2010, 14:52) *
Имеется девайс (pci-карта gpib) с драйверами и .dll + .h с функциями работы с устройством. dll идут под MS Visual C++ и Borland C++ Builder. Можно ли использовать эти .dll без использования вышеуказанных компиляторов? Конкретно интересует gcc/mingw? Если можно, то как?

так как были даны неверные ответы про необходимость lib'ов, я ответила, что да, можно. и привела примеры. у меня интелловский компилятор вполне нормально общается с любыми dll под венду, при этом для работы требуются только заголовочники и сама dll.
Цитата(BRE @ 23.4.2010, 17:46) *
Ни msvcrt.dll, ни kernel32.dll, ни какая другая dll ничего генерить уже не может, генерть может линкер, основываясь на этих самых библиотеках импорта или новые линкеры, которые по сути сами формируют таблицу импорта без генерации этих библиотек.

ну тут я просто неточно выразилась. на самом деле, линкер тащит прототип загрузчика из msvcrt и прилепляет его к модулю. а в kernel32 хранится та самая функция, которая загружает динамически библиотеку при вызове LoadLibrary и выполняет динамическую линковку точек входа при выполнении программы.

я не буду спорить. если хочется зависимости от версии драйвера - делайте как хотите. линкуйте через таблицы импорта. дело ваше. я пояснила, в чём вред такого метода. по-моему, написать пару лишних строк кода и отделаться от перекомпиляции приложения под каждую новую dll от производителя дров - не такая уж плохая идея.
Litkevich Yuriy
Тему разделил: Сборка библиотеки под ОС Symbian
Tonal
Цитата(Iron Bug @ 23.4.2010, 21:57) *
ну тут я просто неточно выразилась. на самом деле, линкер тащит прототип загрузчика из msvcrt и прилепляет его к модулю. а в kernel32 хранится та самая функция, которая загружает динамически библиотеку при вызове LoadLibrary и выполняет динамическую линковку точек входа при выполнении программы.

И опять ты не точно выразилась. :)
msvcrt - это Microsoft C Runtime Libraryю там сидят функции рантайма типа fopen и abort.
А к модулю прицепляется стартовая функция, которая потом вызывает main, или, если модуль собирается в dll-ку, то DllEntryPoint.
Эти стартовые функции свои для каждого компилятора и живут в статических библиотеках.

Цитата(Iron Bug @ 23.4.2010, 21:57) *
я не буду спорить. если хочется зависимости от версии драйвера - делайте как хотите. линкуйте через таблицы импорта. дело ваше. я пояснила, в чём вред такого метода. по-моему, написать пару лишних строк кода и отделаться от перекомпиляции приложения под каждую новую dll от производителя дров - не такая уж плохая идея.

Динамическая линковка возможна как по ординалам, так и по именам.
По именам - по умолчанию, если есть и то и другое.
Т. е. перелинковывать приложение при изменении dll-ки требуется только в том случае, если изменились имена и/или сигнатуры.
Но в этом случае тебе всё равно придётся не только перелинковывать, но корректировать текст вызова и перекомпилять приложение.

Фича динамической линковки в том, что если при старте все указанные dll-ки подгружаются и их импорты разрешаются (резольвятся).
И при обломе приложение не стартует.
Явный минус в том, что на это тратится время и память на старте и dll-ка постоянно висит в памяти, даже в случае, когда она нужна только какой-нибудь редкой и экзотической функции.
Когда это становится критичным, например с плагинами, применяют динамическую загрузку.
Да, в винде есть ещё механизм отложенной загрузки - когда dll-ка подгружается системой не при старте а при первом обращении.

Перечитай Джеффри Рихтер-а "Windows для профессионалов" - там очень подробно описано про динамическую линковку. :)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.