A.1 – Статические и динамические библиотеки
Библиотека – это пакет кода, который предназначен для повторного использования многими программами. Обычно библиотека C++ состоит из двух частей:
- заголовочный файл, который определяет функциональность, которую библиотека предоставляет (предлагает) программам, использующим ее;
- предварительно скомпилированный двоичный файл, который содержит реализацию этой функциональности, предварительно скомпилированную в машинный код.
Некоторые библиотеки могут быть разделены на несколько файлов и/или иметь несколько файлов заголовков.
Библиотеки предварительно скомпилированы по нескольким причинам. Во-первых, поскольку библиотеки меняются редко, их не нужно часто перекомпилировать. Было бы пустой тратой времени перекомпилировать библиотеку каждый раз, когда вы пишете программу, которая ее использует. Во-вторых, поскольку предварительно скомпилированные объекты представлены машинным кодом, люди не могут получить доступ к исходному коду или изменить его, что важно для предприятий или людей, которые не хотят делать свой исходный код доступным из соображений интеллектуальной собственности.
Существует два типа библиотек: статические библиотеки и динамические библиотеки.
Статическая библиотека (иногда называемая archive, «архив») состоит из подпрограмм, которые скомпилированы и линкуются непосредственно с вашей программой. Когда вы компилируете программу, использующую статическую библиотеку, все функции статической библиотеки, которые использует ваша программа, становятся частью вашего исполняемого файла. В Windows статические библиотеки обычно имеют расширение .lib, а в Linux – расширение .a (archive, архив). Одним из преимуществ статических библиотек является то, что вам нужно распространять только исполняемый файл, чтобы пользователи могли запускать вашу программу. Поскольку библиотека становится частью вашей программы, это гарантирует, что с вашей программой всегда будет использоваться правильная версия библиотеки. Кроме того, поскольку статические библиотеки становятся частью вашей программы, вы можете использовать их так же, как функции, которые вы написали для своей программы. С другой стороны, поскольку копия библиотеки становится частью каждого исполняемого файла, который ее использует, это может привести к потере большого количества места. Статические библиотеки также не могут быть легко обновлены – для обновления библиотеки необходимо заменить весь исполняемый файл.
Динамическая библиотека (также называемая shared library, «общая библиотека») состоит из подпрограмм, которые загружаются в ваше приложение во время выполнения. Когда вы компилируете программу, использующую динамическую библиотеку, библиотека не становится частью вашего исполняемого файла – она остается отдельной единицей. В Windows динамические библиотеки обычно имеют расширение .dll (dynamic link library, библиотека динамической компоновки), а в Linux – расширение .so (shared object, общий объект). Одним из преимуществ динамических библиотек является то, что многие программы могут совместно использовать одну копию библиотеки, что экономит место. Возможно, большим преимуществом является то, что динамическую библиотеку можно обновить до более новой версии без замены всех исполняемых файлов, которые ее используют.
Поскольку динамические библиотеки не связаны с вашей программой, программы, использующие динамические библиотеки, должны явно загружать и взаимодействовать с динамической библиотекой. Этот механизм может сбивать с толку и затруднять взаимодействие с динамической библиотекой. Чтобы упростить использование динамических библиотек, можно использовать библиотеку импорта.
Библиотека импорта – это библиотека, которая автоматизирует процесс загрузки и использования динамической библиотеки. В Windows это обычно делается с помощью небольшой статической библиотеки (.lib) с тем же именем, что и динамическая библиотека (.dll). Статическая библиотека подключается к программе во время компиляции, и затем функциональные возможности динамической библиотеки можно эффективно использовать, как если бы это была статическая библиотека. В Linux файл общих объектов (.so) выполняет функции динамической библиотеки и библиотеки импорта. Большинство компоновщиков при создании динамической библиотеки могут создать библиотеку импорта для этой динамической библиотеки.
Установка и использование библиотек
Теперь, когда вы знаете о различных типах библиотек, давайте поговорим о том, как на самом деле использовать библиотеки в вашей программе. Установка библиотеки на C++ обычно состоит из 4 шагов:
- Получите библиотеку. Лучший вариант – загрузить предварительно скомпилированный пакет для вашей операционной системы (если он существует), чтобы вам не пришлось компилировать библиотеку самостоятельно. Если для вашей операционной системы не предусмотрен пакет, вам придется загрузить пакет, содержащий только исходный код, и скомпилировать его самостоятельно (что выходит за рамки этого урока). В Windows библиотеки обычно распространяются в виде файлов .zip. В Linux библиотеки обычно распространяются в виде пакетов (например, .RPM). В вашем диспетчере пакетов могут быть некоторые из наиболее популярных библиотек (например, SDL), которые уже перечислены для упрощения установки, поэтому сначала проверьте там.
- Установите библиотеку. В Linux это обычно включает вызов диспетчера пакетов и предоставление ему возможности выполнить всю работу. В Windows это обычно включает разархивирование библиотеки в каталог по вашему выбору. Для облегчения доступа рекомендуем хранить все свои библиотеки в одном месте. Например, используйте каталог C:\libs и поместите каждую библиотеку в отдельный подкаталог.
- Убедитесь, что компилятор знает, где искать файл(ы) заголовков для данной библиотеки. В Windows обычно это подкаталог include каталога, в который вы установили файлы библиотеки (например, если вы установили свою библиотеку в C:\libs\SDL-1.2.11, файлы заголовков, вероятно, находятся в C:\libs\SDL-1.2.11\include). В Linux файлы заголовков обычно устанавливаются в /usr/include, который уже должен быть частью пути поиска включаемых файлов. Однако если файлы установлены в другом месте, вам придется указать компилятору, где их найти.
- Сообщите компоновщику, где искать файл(ы) библиотеки. Как и в шаге 3, это обычно включает добавление каталога в список мест, где компоновщик ищет библиотеки. В Windows это обычно подкаталог /lib каталога, в который вы установили файлы библиотеки. В Linux библиотеки обычно устанавливаются в /usr/lib, который уже должен быть частью пути поиска ваших библиотек.
После того, как библиотека установлена, и среда IDE знает, где ее искать, обычно необходимо выполнить следующие 3 шага для каждого проекта, который хочет использовать библиотеку:
- Если вы используете статические библиотеки или библиотеки импорта, сообщите компоновщику, какие файлы библиотеки нужно линковать.
- Включите с помощью
#include
заголовочный файл(ы) библиотеки в вашу программу. Это сообщит компилятору обо всех функциях, предлагаемых библиотекой, чтобы ваша программа могла правильно компилироваться. - Если вы используете динамические библиотеки, убедитесь, что программа знает, где их найти. В Linux библиотеки обычно устанавливаются в /usr/lib, который находится в пути поиска по умолчанию после путей в переменной среды
LD_LIBRARY_PATH
. В Windows путь поиска по умолчанию включает каталог, из которого запускается программа, каталоги, установленные вызовомSetDllDirectory()
, каталоги Windows, System и System32, а также каталоги в переменной средыPATH
. Самый простой способ использовать .dll – скопировать .dll в расположение исполняемого файла. Поскольку вы обычно распространяете .dll вместе со своим исполняемым файлом, в любом случае имеет смысл хранить их вместе.
Шаги 3-5 включают настройку вашей IDE – к счастью, когда дело доходит до выполнения этих вещей, почти все IDE работают одинаково. К сожалению, поскольку каждая среда IDE имеет свой интерфейс, самая сложная часть этого процесса – просто определить правильное место для выполнения каждого из этих шагов. Следовательно, в следующих нескольких уроках этого раздела мы расскажем, как выполнить все эти шаги как для Visual Studio, так и для Code::Blocks. Если вы используете другую IDE, прочтите оба урока – к тому времени, когда вы закончите, у вас должно быть достаточно информации, чтобы сделать то же самое с вашей собственной IDE и небольшим гуглением.