Создание DLL-модуля
Создавая DLL, Вы создаете набор функций, которые могут быть вызваны из ЕХЕ-модуля (или другой DLL), DLL может экспортировать переменные, функции или C++ классы в другие модули. На самом дслс я бы не советовал экспортировать переменные, потому что это снижает уровень абстрагирования Вашего кода и усложняет его поддержку. Кроме того, С++-классы можно экспортировать, только если импортирующие их модули транслируются тем же компилятором. Так что избегайте экспорта С++-классов, если Вы не уверены, что разработчики ЕХЕ-модулей будут пользоваться тем же компилятором.
При разработке DLL Вы сначала создаете заголовочный файл, в котором содержатся экспортируемые из нее переменные (типы и имена) и функции (прототипы и имена). В этом же файле надо определить все идентификаторы и структуры данных, используемые экспортируемыми функциями и переменными. Заголовочный файл включается во всс модули исходного кода Вашей DLL Более того, Вы должны поставлять его вместе со своей DLL, чтобы другие разработчики могли включать его в свои модули исходного кода, которые импортируют Ваши функции или переменные Единый заголовочный файл, используемый при сборке DLL и любых исполняемых модулей, существенно облегчает поддержку приложения.
Вот пример единого залоловочного файла, включаемого в исходный код DLL- и ЕХЕ-модулей.
Модуль MyLib.h
Этот заголовочный файл надо включать в самое начало исходных файлов Вашей DLL следующим образом:
MyLibFile1.cpp
При компиляции исходного файла DLL, показанного на предыдущем листинге, MYLIBAPI определяется как __declspec(dllexport) до включения заголовочного файла MyLib.h. Такой модификатор означает, что данная переменная, функция или С++-класс экспортируется из DLL Заметьте, что идентификатор MYLIBAPI помещен и заголовочный файл до определения экспортируемой переменной или функции.
Также обратите внимание, что в файле MyLibFilel.cpp перед экспортируемой переменной или функцией не ставится идентификатор MYITBAPI. Он здесь не нужен, проанализировав заголовочный файл, компилятор запоминает, какие переменные и функции являются экспортируемыми.
Идентификатор MYLIRAPT включает extern. Пользуйтесь этим модификатором только в коде на С++, но ни в коем случае не в коде на стандартном С. Обычно компиляторы С++ искажают (mangle) имена функций и переменных, что может приводить к серьезным ошибкам при компоновке. Представьте, что DLL написана на С++, а исполняемый код — на стандартном С. При сборке DLL имя функции будет искажено, но при сборке исполняемого модуля — нет. Пытаясь скомпоновать исполняемый модуль, компоновщик сообщит об ошибке исполняемый модуль обращается к несуществующему идентификатору Модификатор extern не дает компилятору искажать имена переменных или функций, и они становятся доступными исполняемым модулям, написанным на С, С++ или любом другом языке программирования.
Теперь Вы знаете, как используется заголовочный файл в исходных файлах DLL. А как насчет исходных файлов ЕХЕ-модули? В них MYLIBAPI определять не надо: включая заголовочный файл, Вы определяете этот идентификатор как __declspec(dllimport), и при компиляции исходного кода ЕХЕ-модуля компилятор поймет, что переменные и функции импортируются из DLL.
Просмотрев стандартные заголовочные файлы Windows (например, WinBase.h), Вы обнаружите, что практически тот же подход исповедует и Microsoft.