Советы по Delphi

         

Динамическое использование DLL


...возможно ли заставить Delphi осуществлять только линковку ссылок на необходимые приложению DLL-функции с помощью директив компилятора или чего-то подобного? Я могу с ними динамически связаться с помощью GetProcAddress или функций линковки, но я был бы счастлив если была бы альтернатива попроще. (стилистика авторская - В.О.)

Нет, даже в вашем случае вы должны использовать динамическое связывание...

Часто кажется, что проще написать в модуле явное импортирование функций, чем использовать их динамическое связывание. Тем не менее, основное преимущество динамически загружаемых DLL в том, что ваше приложение может быть загружено и быть работоспособным и в случае отсутствия DLL, при условии, что приложение может к этому "приспособиться". Например, если если вы реализовали в своей DLL трехмерное представление вашего объекта, но DLL не была найдена (при попытке загрузить ее динамически), то приложение также будет работать, но объекты будут представлены в обычном, двумерном виде. Если DLL, о которой идет речь, будет связана статически, Windows откажется выполнять приложение (с претензией, что ваша 3D.DLL не была обнаружена), чему пользователь будет "неслыханно рад". Другое преимущество явного импорта в модуле в том, что приложение будет загружаться быстрее, поскольку динамически подгружаемые DLL будут загружены впоследствии, когда они действительно понадобятся.

Проследим, что получается, если вы используете в модуле явный импорт DLL или в вашем коде вы объявляете функцию DLL с внешним 'DLLNAME'. В этом случае компоновщик установит ссылки на DLL-функции в таблице импортируемых имен скомпонованного EXE-файла и загрузчик Windows автоматически загрузит DLL (во время выполнения главного блока) вместе с файлом EXE:

    procedure Foo(X: Integer); external 'BAR' index 1;

Если в течение связывания (также называемое статической линковкой) Windows не сможет найти DLL, вы получите предупреждение - чаще всего File Error MessageBox (как раз то, в котором не указан ненайденный файл - ну очень "полезная" штуковина!). Поэтому вы должны быть абсолютно уверенными в том, что DLL будет доступна все то время, когда вы захотите ей воспользоваться, т.е. всегда.

Динамически связанная DLL, использующая модуль явного импорта, пользуется методами VB, каковые вы также можете использовать, но делая это "вручную". С помощью LoadLibrary по мере необходимости вы загружаете DLL, получаете указатели на экспортируемые функции, которые вы предполагаете использовать с GetProcAddress и освобождаете DLL с помощью FreeLibrary, когда она вам больше не нужна:



    var Hbar: Thandle; Foo: procedure (X: Integer); begin Hbar := LoadLibrary('BAR.DLL'); if Hbar >= 32 then { успешно } begin Foo := GetProcAddress(HBar, 'FOO'); ... Foo(1); ... FreeLibrary(HBar); end else MessageDlg('Ошибка: не могу найти BAR.DLL', mtError, [mbOk], 0) end.

Успехов,
Dr. Bob (drbob@pi.net) [000726]



Содержание раздела