Шаг 66.
Библиотека OWL.
Сравнение DLL с программами

    На этом шаге мы сравним программы и DLL.

    Хотя в DLL-библиотеках и могут содержаться те функции, которые может вызвать ваша программа, сами по себе DLL-библиотеки не являются выполняемыми файлами. Даже если изменить расширение этих файлов на ЕХЕ, Windows все равно не заставит работать DLL-библиотеку. (Действительно, многие DLL-библиотеки Windows и имеют расширения ЕХЕ, например USER.EXE и GDI.EXE.) Файл DLL-библиотеки может иметь любое расширение. Однако, Windows автоматически загружает библиотеки только с расширением DLL. Если вы хотите использовать функции, содержащиеся в DLL, то DLL-библиотека должна быть загружена Windows или вашей программой с помощью вызова функции LoadLibrary().

    Так как DLL не является выполняемой программой, то вы вправе предположить, что существуют определенные существенные различия в способах создания выполняего файла и файла DLL. Одним из них является тип файла определений, используемого для DLL.

    Ниже приводится пример файла определения:

LIBRARY	     SHAPELIB
DESCRIPTION 'Shape DLL for Windows'	
EXETYPE	     WINDOWS
CODE	     PRELOAD MOVEABLE DISCARDABLE
DATA	     PRELOAD MOVEABLE SINGLE
HEAPSIZE    1024

    Файл определения исполняемой программы содержит поле NAME; однако вместо него в определении DLL требуется после LIBRARY. Строка LIBRARY идентифицирует этот модуль как библиотеку и присваивает ей имя. Строки EXETYPE и CODE используются одинаковым образом для выполняемых программ и для DLL. Однако в строке DATA имеется важное различие. Слово SINGLE означает, что DLL-библиотека имеет только один сегмент данных. Так как в Windows загружается только один экземпляр DLL, ему и требуется только один сегмент данных. Выполняемые файлы могут иметь несколько сегментов данных, так как для каждого из экземпляров программы требуется свой собственный сегмент данных. Можно иметь DLL без сегментов данных, используя строку DATA NONE.

    В последней строке предыдущего файла описания указывается начальный размер динамической области DLL. Если этот размер оказывается слишком малым, Windows при необходимости может его увеличить. Отметим, что в файле определения отсутствует строка STACKSIZE. Это обусловлено тем, что DLL всегда совместно использует стек той программы, которая ее вызвала, поэтому DLL не нуждается в собственном стеке. Это различие между DLL и программой, тем не менее, приводит к неприятной ситуации, известной на практике как DS ! = SS. К счастью, IDE Borland знает, как справиться с такой проблемой, и не считает, что для DLL DS == SS, если сделана правильная установка.


    Замечание. В языке C все глобальные и статические переменные хранятся в статической памяти (в динамически распределяемой области, или "куче"), а все параметры функций и локальных переменных хранятся в стеке. Статическая память адресуется как смещение относительно регистра DS (сегмента данных). Аналогично стек адресуется как смещение относительно SS (сегмента стека). К сожалению, по причинам, которые не рассматриваются здесь, C-компилятор не может знать, что представляет собой близкий (near) указатель - смещение относительно DS или относительно SS. Чтобы разрешить эту проблему, С-программы (а также С++-программы) устанавливают для сегмента данных и сегмента стека один и тот же адрес.

    Другими словами, DS = SS. В обычных Windows-программах, которые имеют собственные сегменты данных и стеков, это не представляет затруднений. Тем не менее, DLL имеет собственный сегмент данных и использует стек вызывающей программы; это и означает DS != SS. В этом случае, функции в DLL, в которых для адресации сегмента стека используется близкий (near) указатель, не в состоянии найти свои данные. Однако, когда для создания вашей DLL используется IDE Borland С++, вам не надо беспокоиться об этой проблеме, так как вы можете установить компилятор таким образом, чтобы он знал, что DS никогда не равно SS при построении DLL.


    На следующем шаге мы рассмотрим алгоритм построения простой DLL.




Предыдущий шаг Содержание Следующий шаг