|
DLL (англ. Dynamic-link library — динамически подключаемая библиотека) — понятие операционной системы Microsoft Windows; динамическая библиотека, позволяющая многократное применение различными программными приложениями. K DLL относятся также элементы управления ActiveX и драйвера. В мире UNIX аналогичные функции выполняют т. н. shared objects («разделяемые объекты»). Формат файлов DLL придерживается тех же соглашений, что и формат исполняемых файлов, сочетая код, таблицы и ресурсы.
Цели введения DLL Первоначально предполагалось, что введение DLL позволит эффективно организовать память и дисковое пространство, используя только одну инстанцию библиотечных модулей для многих приложений. Это было особенно важно для ранних версий Microsoft Windows с жёсткими ограничениями по памяти. Далее, предполагалось улучшить эффективность разработок и использования системных средств за счёт модульности. Замена DLL-программ с одной версии на другую должна была позволить независимо наращивать систему, не затрагивая приложений. Кроме того, библиотеки DLL могли использоваться разнотипными приложениями — например, Microsoft Office, Microsoft Visual Studio и т. п. В дальнейшем идея модульности выросла в концепцию COM. Фактически, полных преимуществ от внедрения DLL получить не удалось по причине явления, называемого DLL Hell («ад DLL»). DLL Hell возникает, когда несколько приложений требуют одновременно различные, не полностью совместимые, версий DLL-библиотек, что приводит к сбоям в этих приложениях. Когда система выросла до определённых размеров, количество DLL стало превышать многие тысячи, не все из них обладали полной надёжностью и совместимостью, и конфликты типа DLL Hell стали возникать очень часто, резко понижая общую надёжность системы. Поздние версии Microsoft Windows стали разрешать параллельное использование разных версий DLL, что свело на нет преимущества изначального принципа модульности. Примеры использования DLL в разных языках
Экспорт из DLL
Delphilibrary Example; <span class="coMULTI"><em><font color="#808080">{ Производим некие действия и возвращаем результат }</font></em></span> <span class="kw1"><strong>function</strong></span> AddNumbers<span class="br0"><font color="#66cc66">(</font></span>a, b: <span class="kw4"><font color="#993333">Double</font></span><span class="br0"><font color="#66cc66">)</font></span>: <span class="kw4"><font color="#993333">Double</font></span>; <span class="kw1"><strong>cdecl</strong></span>; <span class="kw1"><strong>begin</strong></span> AddNumbers := a + b <span class="kw1"><strong>end</strong></span>; <span class="coMULTI"><em><font color="#808080">{ Эта функция экспортируется }</font></em></span> exports AddNumbers; <span class="coMULTI"><em><font color="#808080">{ Инициализационная функция DLL, аналог main() }</font></em></span> <span class="kw1"><strong>begin</strong></span> <span class="kw1"><strong>end</strong></span>.
C и C++<span class="co2"><font color="#339900">#include <windows.h></font></span> <span class="coMULTI"><em><font color="#ff0000">/* Эта функция экспортируется */</font></em></span> <span class="kw4"><font color="#0000ff">extern</font></span> <span class="st0"><font color="#666666">"C"</font></span> __declspec<span class="br0">(</span>dllexport<span class="br0">)</span> <span class="kw4"><font color="#0000ff">double</font></span> AddNumbers<span class="br0">(</span><span class="kw4"><font color="#0000ff">double</font></span> a, <span class="kw4"><font color="#0000ff">double</font></span> b<span class="br0">)</span>; <span class="coMULTI"><em><font color="#ff0000">/* Инициализационная функция DLL, аналог main() */</font></em></span> <span class="kw4"><font color="#0000ff">BOOL</font></span> APIENTRY DllMain<span class="br0">(</span>HANDLE hModule, DWORD dwReason, LPVOID lpReserved<span class="br0">)</span> <span class="br0">{</span> <span class="kw1"><font color="#0000ff">return</font></span> <span class="kw2"><font color="#0000ff">TRUE</font></span>; <span class="br0">}</span> <span class="coMULTI"><em><font color="#ff0000">/* Производим некие действия и возвращаем результат */</font></em></span> <span class="kw4"><font color="#0000ff">double</font></span> AddNumbers<span class="br0">(</span><span class="kw4"><font color="#0000ff">double</font></span> a, <span class="kw4"><font color="#0000ff">double</font></span> b<span class="br0">)</span> <span class="br0">{</span> <span class="kw1"><font color="#0000ff">return</font></span> a + b; <span class="br0">}</span>
Импорт из DLL
Delphi<span class="kw1"><strong>program</strong></span> Example; <span class="coMULTI"><em><font color="#808080">{$APPTYPE CONSOLE}</font></em></span> <span class="coMULTI"><em><font color="#808080">{ Указываем, что функция находится в DLL }</font></em></span> <span class="kw1"><strong>function</strong></span> AddNumbers<span class="br0"><font color="#66cc66">(</font></span>a, b: <span class="kw4"><font color="#993333">Double</font></span><span class="br0"><font color="#66cc66">)</font></span>: <span class="kw4"><font color="#993333">Double</font></span>; <span class="kw1"><strong>cdecl</strong></span>; external <span class="st0"><font color="#ff0000">'Example.dll'</font></span>; <span class="coMULTI"><em><font color="#808080">{ Используем функцию как обычно }</font></em></span> <span class="kw1"><strong>var</strong></span> result: <span class="kw4"><font color="#993333">Double</font></span>; <span class="kw1"><strong>begin</strong></span> result := AddNumbers<span class="br0"><font color="#66cc66">(</font></span><span class="nu0"><font color="#cc66cc">1</font></span>, <span class="nu0"><font color="#cc66cc">2</font></span><span class="br0"><font color="#66cc66">)</font></span>; <span class="kw3"><font color="#000066">Writeln</font></span><span class="br0"><font color="#66cc66">(</font></span><span class="st0"><font color="#ff0000">'The result was: '</font></span>, result<span class="br0"><font color="#66cc66">)</font></span> <span class="kw1"><strong>end</strong></span>.
C и C++<span class="co2"><font color="#339900">#include <stdio.h></font></span> <span class="coMULTI"><em><font color="#ff0000">/* * Указываем, что тело функции находится в другом файле. * Не забыть про объектный модуль DLL при линковке! */</font></em></span> <span class="kw4"><font color="#0000ff">extern</font></span> <span class="st0"><font color="#666666">"C"</font></span> __declspec<span class="br0">(</span>dllimport<span class="br0">)</span><span class="kw4"><font color="#0000ff">double</font></span> AddNumbers<span class="br0">(</span><span class="kw4"><font color="#0000ff">double</font></span> a, <span class="kw4"><font color="#0000ff">double</font></span> b<span class="br0">)</span>; <span class="coMULTI"><em><font color="#ff0000">/* Используем функцию как обычно */</font></em></span> <span class="kw4"><font color="#0000ff">int</font></span> main<span class="br0">(</span><span class="kw4"><font color="#0000ff">int</font></span> argc, <span class="kw4"><font color="#0000ff">char</font></span> **argv<span class="br0">)</span> <span class="br0">{</span> <span class="kw4"><font color="#0000ff">double</font></span> result = AddNumbers<span class="br0">(</span><span class="nu0"><font color="#0000dd">1</font></span>, <span class="nu0"><font color="#0000dd">2</font></span><span class="br0">)</span>; <span class="kw3"><font color="#0000dd">printf</font></span><span class="br0">(</span><span class="st0"><font color="#666666">"The result was: %f<span class="es0"><strong>\n</strong></span>"</font></span>, result<span class="br0">)</span>; <span class="kw1"><font color="#0000ff">return</font></span> <span class="nu0"><font color="#0000dd">0</font></span>; <span class="br0">}</span>
Подгрузка и импорт из DLL во время работы
Visual Basic<span class="kw1"><font color="#b1b100">Option</font></span> <span class="kw1"><font color="#b1b100">Explicit</font></span> <span class="co1"><font color="#808080">' Указываем, что функция находится во внешней DLL.</font></span> <span class="kw1"><font color="#b1b100">Declare</font></span> <span class="kw1"><font color="#b1b100">Function</font></span> AddNumbers <span class="kw1"><font color="#b1b100">Lib</font></span> <span class="st0"><font color="#ff0000">"Example.dll"</font></span> _ <span class="br0"><font color="#66cc66">(</font></span><span class="kw1"><font color="#b1b100">ByVal</font></span> a <span class="kw1"><font color="#b1b100">As</font></span> <span class="kw1"><font color="#b1b100">Double</font></span>, <span class="kw1"><font color="#b1b100">ByVal</font></span> b <span class="kw1"><font color="#b1b100">As</font></span> <span class="kw1"><font color="#b1b100">Double</font></span><span class="br0"><font color="#66cc66">)</font></span> <span class="kw1"><font color="#b1b100">As</font></span> <span class="kw1"><font color="#b1b100">Double</font></span> <span class="co1"><font color="#808080">' Используем функцию как обычно</font></span> <span class="kw1"><font color="#b1b100">Sub</font></span> Main<font color="#66cc66"><span class="br0">(</span><span class="br0">)</span></font> <span class="kw1"><font color="#b1b100">Dim</font></span> Result <span class="kw1"><font color="#b1b100">As</font></span> <span class="kw1"><font color="#b1b100">Double</font></span> Result = AddNumbers<span class="br0"><font color="#66cc66">(</font></span><span class="nu0"><font color="#cc66cc">1</font></span>, <span class="nu0"><font color="#cc66cc">2</font></span><span class="br0"><font color="#66cc66">)</font></span> Debug.<span class="kw1"><font color="#b1b100">Print</font></span> <span class="st0"><font color="#ff0000">"The result was: "</font></span> & Result <span class="kw1"><font color="#b1b100">End</font></span> <span class="kw1"><font color="#b1b100">Sub</font></span>
C и C++<span class="co2"><font color="#339900">#include <windows.h></font></span> <span class="co2"><font color="#339900">#include <stdio.h></font></span> <span class="coMULTI"><em><font color="#ff0000">/* * Тип используемой функции * (комбинация типов параметры и возвращаемого значения) */</font></em></span> <span class="kw4"><font color="#0000ff">typedef</font></span> <span class="kw4"><font color="#0000ff">double</font></span> <span class="br0">(</span>*importFunction<span class="br0">)</span><span class="br0">(</span><span class="kw4"><font color="#0000ff">double</font></span>, <span class="kw4"><font color="#0000ff">double</font></span><span class="br0">)</span>; <span class="kw4"><font color="#0000ff">int</font></span> main<span class="br0">(</span><span class="kw4"><font color="#0000ff">int</font></span> argc, <span class="kw4"><font color="#0000ff">char</font></span> **argv<span class="br0">)</span> <span class="br0">{</span> importFunction addNumbers; <span class="kw4"><font color="#0000ff">double</font></span> result; <span class="coMULTI"><em><font color="#ff0000">/* Загружаем DLL в память */</font></em></span> HINSTANCE hinstLib = LoadLibrary<span class="br0">(</span><span class="st0"><font color="#666666">"Example.dll"</font></span><span class="br0">)</span>; <span class="kw1"><font color="#0000ff">if</font></span> <span class="br0">(</span>hinstLib == <span class="kw2"><font color="#0000ff">NULL</font></span><span class="br0">)</span> <span class="br0">{</span> <span class="kw3"><font color="#0000dd">printf</font></span><span class="br0">(</span><span class="st0"><font color="#666666">"ERROR: unable to load DLL<span class="es0"><strong>\n</strong></span>"</font></span><span class="br0">)</span>; <span class="kw1"><font color="#0000ff">return</font></span> <span class="nu0"><font color="#0000dd">1</font></span>; <span class="br0">}</span> <span class="coMULTI"><em><font color="#ff0000">/* Получаем указатель на функцию */</font></em></span> addNumbers = <span class="br0">(</span>importFunction<span class="br0">)</span>GetProcAddress<span class="br0">(</span>hinstLib, <span class="st0"><font color="#666666">"AddNumbers"</font></span><span class="br0">)</span>; <span class="kw1"><font color="#0000ff">if</font></span> <span class="br0">(</span>addNumbers == <span class="kw2"><font color="#0000ff">NULL</font></span><span class="br0">)</span> <span class="br0">{</span> <span class="kw3"><font color="#0000dd">printf</font></span><span class="br0">(</span><span class="st0"><font color="#666666">"ERROR: unable to find DLL function<span class="es0"><strong>\n</strong></span>"</font></span><span class="br0">)</span>; <span class="kw1"><font color="#0000ff">return</font></span> <span class="nu0"><font color="#0000dd">1</font></span>; <span class="br0">}</span> <span class="coMULTI"><em><font color="#ff0000">/* Вызываем функцию через указатель */</font></em></span> result = addNumbers<span class="br0">(</span><span class="nu0"><font color="#0000dd">1</font></span>, <span class="nu0"><font color="#0000dd">2</font></span><span class="br0">)</span>; <span class="coMULTI"><em><font color="#ff0000">/* * Выгружаем DLL (в принципе, это будет сделано * автоматически при выходе из программы) */</font></em></span> FreeLibrary<span class="br0">(</span>hinstLib<span class="br0">)</span>; <span class="coMULTI"><em><font color="#ff0000">/* Отображаем результат */</font></em></span> <span class="kw3"><font color="#0000dd">printf</font></span><span class="br0">(</span><span class="st0"><font color="#666666">"The result was: %f<span class="es0"><strong>\n</strong></span>"</font></span>, result<span class="br0">)</span>; <span class="kw1"><font color="#0000ff">return</font></span> <span class="nu0"><font color="#0000dd">0</font></span>; <span class="br0">}</span>
Delphi<span class="kw1"><strong>program</strong></span> Example; <span class="coMULTI"><em><font color="#808080">{$APPTYPE CONSOLE}</font></em></span> <span class="kw1"><strong>var</strong></span> result: <span class="kw4"><font color="#993333">Double</font></span>; LibHandle: Hmodule; AddNumbers: <span class="kw1"><strong>function</strong></span><span class="br0"><font color="#66cc66">(</font></span>a, b: <span class="kw4"><font color="#993333">Double</font></span><span class="br0"><font color="#66cc66">)</font></span>: <span class="kw4"><font color="#993333">Double</font></span>; <span class="kw1"><strong>begin</strong></span> LibHandle := LoadLibrary<span class="br0"><font color="#66cc66">(</font></span><span class="st0"><font color="#ff0000">'Example.dll'</font></span><span class="br0"><font color="#66cc66">)</font></span>; <span class="co1"><em><font color="#808080">// загружаем DLL</font></em></span> <span class="kw1"><strong>if</strong></span> LibHandle <> <span class="nu0"><font color="#cc66cc">0</font></span> <span class="kw1"><strong>then</strong></span> <span class="kw1"><strong>begin</strong></span> @AddNumbers := GetProcAddress<span class="br0"><font color="#66cc66">(</font></span>LibHandle, <span class="st0"><font color="#ff0000">'AddNumbers'</font></span><span class="br0"><font color="#66cc66">)</font></span>; <span class="co1"><em><font color="#808080">// запоминаем адрес</font></em></span> <span class="co1"><em><font color="#808080">// необходимой функции</font></em></span> <span class="kw1"><strong>if</strong></span> @AddNumbers <> <span class="kw2"><strong>nil</strong></span> <span class="kw1"><strong>then</strong></span> <span class="kw1"><strong>begin</strong></span> result := AddNumbers<span class="br0"><font color="#66cc66">(</font></span><span class="nu0"><font color="#cc66cc">1</font></span>, <span class="nu0"><font color="#cc66cc">2</font></span><span class="br0"><font color="#66cc66">)</font></span>; <span class="co1"><em><font color="#808080">// используем функцию</font></em></span> <span class="kw3"><font color="#000066">Writeln</font></span><span class="br0"><font color="#66cc66">(</font></span><span class="st0"><font color="#ff0000">'The result was: '</font></span>, result<span class="br0"><font color="#66cc66">)</font></span>; <span class="kw1"><strong>end</strong></span>; FreeLibrary<span class="br0"><font color="#66cc66">(</font></span>LibHandle<span class="br0"><font color="#66cc66">)</font></span>; <span class="co1"><em><font color="#808080">// выгружаем DLL</font></em></span> <span class="kw1"><strong>end</strong></span>; <span class="kw1"><strong>end</strong></span>.
Copyright 2007. All Rights Reserved. |