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