Создание библиотек программирования в общем напоминает создание обычных приложений, однако есть определённые тонкости.
В заголовочном файле библиотеки описываются ресурсы, предназначенные для экспорта (то есть для использования программами). Эти ресурсы называются интерфейсом библиотеки (или программным интерфейсом библиотеки – API от Application Programming Interface). Пример заголовочного файла статической библиотеки, описывающей работу с комплексными числами, представлен на листинге 1. Как видно, это обычное объявление класса.
Листинг 1. Заголовочный файл библиотеки комплексных чисел.
Заголовочные файлы могут включаться в проект несколько раз. Это может вызывать избыточное определение типов данных и переменных, что будет приводить к ошибкам компиляции. Именно поэтому описание ресурсов библиотек в заголовочных файлах заключается между директивами препроцессора
#ifndefCONSTANT_NAME#defineCONSTANT_NAME//…#endif
Эти директивы на этапе препроцессирования программного кода позволяют включать определения ресурсов только один раз.
Компиляторы фирмы Microsoft (и Intel) позволяют использовать вместо конструкции ветвления препроцессора конструкцию
#pragmaonce
Что является предписанием компилятору, что данный файл подключается только раз.
Реализация объявленных в заголовочном файле ресурсов происходит, как и обычно, в файле cpp.
В случае разработки динамических библиотек, их создание может происходить аналогично созданию статических библиотек. Особенностью, в данном случае, будет только выбор типа проекта. В этом случае библиотека может использоваться неявно (то есть, через подключение заголовочного файла и указание использования файла импорта библиотеки). Для использования функций библиотеки необходимо явно указать, к каким функциям может получить доступ зависимая от данной библиотеки программа. Для этого используется специальная конструкция языка __declspec(dllexport), указывающая, что функция (класс) доступна для использования. В листинге 3 представлен пример заголовочного файла, в котором описан класс комплексного числа. Этот класс предназначен на экспорт.
Также функции на экспорт можно определить при помощи def-файла (файл определения модуля), что позволяет не использовать конструкцию __declspec(dllexport). Файл определения модуля описывается по следующим правилам:
Первая строка файла есть указание имени библиотеки, при помощи инструкции LIBRARY.
Вторая секция открывается инструкцией EXPORTS, она указывает, какие части библиотеки идут на экспорт. Каждая следующая строка представляет имя функции и порядковый номер в библиотеке, выделенный символом @.
Описанный в листингах 2 и 3, класс можно использовать только в С++ проектах. Для создания библиотек, совместимых с языком С, необходимо заголовочные файлы писать в стиле С (без использования классов, шаблонов и др. специфичные для С++ конструкции). Также желательно в макросе DLLEXPORT приписать модификатор extern ”C” – это позволяет, при компиляции библиотеки, сохранить оригинальные имена экспортируемых ресурсов (некоторые компиляторы «кодируют» имена функций и классов).
Использование динамической библиотеки, созданной таким образом, не будет возможно в других, отличных от С/С++, языках программирования. Это связанно с тем, что в языках Pascal, Basic и др. функции читают входные параметры слева направо, тогда как в С/С++ входные параметры читаются справа налево. Для создания совместимой с этой группой языков библиотеки используется модификатор __stdcall (или эквивалент __pascal), который меняет порядок чтения входных параметров функции.
В OS Windows динамические библиотеки могут иметь также точку входа - функцию DllMain:
Самый простой способ создания библиотек - выбор соответстувующего проекта в среде программирования. Все современные среды программирования предлагают проекты как статических, так и динамических библиотек.
Разработка статических библиотек ничем не отличается от написания программы, только в статических библиотеках нет функции main.