Как подключить библиотеку в программу на C++?

Как же подключить/загрузить внешнюю динамическую библиотеку в свою программу/проект, написанную на языке программирования C++ в IDE Microsoft Visual Studio, в ОС Microsoft Windows?

Состав

Типы файлов

Для начала, давайте разберёмся, что обычно представляет собой любая динамическая библиотека, написанная на, и созданная для программ С++? Это от 1 до 4 типов файлов:

  • Some.h — заголовочный файл, который объявляет функционал библиотеки, i.e., заголовочный текстовый файл с определениями всех доступных сущностей (переменных, констант, классов, методов, etc) данной библиотеки, которые можно вызывать и использовать.
  • Some.dll — предварительно скомпилированный бинарный файл, содержащий реализацию функционала библиотеки, т.е. непосредственно, сама динамическая библиотека. Чаще именуется просто как «dll библиотека».
  • Some.lib — библиотека импорта, содержащая таблицу импорта библиотеки. Это не статическая библиотека. Несмотря на то, что расширение файла библиотеки импорта совпадает со стандартным расширением статических библиотек, путать их не стоит.
  • Some.exp — библиотека экспорта, содержащая таблицу экспорта библиотеки.

Из всего списка главным являются только файлы с расширением .dll, т.е. остальных файлов может и не быть.

Количество

У одной библиотеки может быть множество файлов таких типов. Все они, обычно, рассортированы по соответствующим папкам, чтобы было легче подключать в IDE.

Вариации

Файлы dll, lib и exp различаются по платформе (ОС), архитектуре, конфигурации, etc. В одной версии библиотеки может предоставляться сразу несколько альтернативных вариаций одинаковых по функционалу файлов. E.g.:

  • Для x32 (x86) и x64 архитектуры/платформы.
  • Для конфигурации Release, Debug, etc. Для Debug конфигурации часто используются библиотеки с постфиксом *-d.dll, а для Release — без него.
  • Для разных IDE.
  • Для разных ОС. Составные файлы библиотек компилируется под каждую ОС отдельно, т.е. содержание и расширение зависит от ОС. E.g., в ОС MS Windows динамические библиотеки имеют расширение .dll, а в GNU/Linux — .so; статические в Win имеют расширение .lib, в ОС GNU/Linux — .a, соответственно.

Всё это крайне важно, всё надо учитывать при подключении библиотеки к проекту. Свойства проекта в Visual C++ могут устанавливаться отдельно для каждой конфигурации (Release, Debug) и архитектуры/платформы (x32 (x86), x64).

Подключение

Перед тем, как подключать файлы библиотеки к своей программе, надо сперва открыть необходимый проект в IDE Visual Studio: Главное меню > Файл > Открыть проект.

Заголовочные файлы (.h)

Заголовочных файлов чаще всего больше одного. Все они, обычно, находятся в папке «include» в любой библиотеке.
Каталог с заголовчными файлами (.h) библиотеки указывать здесь: Главное меню > Проект > Свойства проекта > Свойства конфигурации > C/C++ > Общие > Дополнительные каталоги включаемых файлов.

Помимо указания IDE директории расположения заголовочных файлов (.h), их также по мере необходимости надо дополнительно явно указывать в коде с помощью директивы препроцессора #include. Необходимые заголовочные файлы подключаются в коде только там, где они нужны, т.е. где используются сущности определённые в этих файлах. Заголовочные файлы можно подключать как в файле с кодом (.cpp), так и в заголовочном файле (.h), но лучше подключать именно в заголовочном файле, а в файле кода не подключать, там подключить только свой заголовочный файл. В каждом заголовочном файле подключать требуемые заголовочные файлы так:

#include "some.h"
#include "foo.h"

Файлы таблиц импорта и экспорта (.lib, .exp)

Файлы таблиц импорта и экспорта (.lib, .exp), обычно, находятся в папке «lib» в любой библиотеке.
Каталог с файлами таблиц импорта (.lib) библиотеки указывать здесь: Главное меню > Проект > Свойства проекта > Свойства конфигурации > Компоновщик > Общие > Дополнительные каталоги библиотек.

Файл таблицы импорта (.lib)

Помимо указания IDE директории расположения файлов таблиц импорта (.lib), их также для линковки надо дополнительно явно указать. Сделать это можно двумя способами:

    1. Прописать полные названия (путь, название и расширение) .lib файлов сюда: Главное меню > Проект > Свойства проекта > Свойства конфигурации > Компоновщик > Ввод > Дополнительные зависимости. Каждая библиотека в отдельной строке. Кавычки необязательны.
      В итоге они будут вписаны автоматически в строку в двойных кавычках через точку с запятой (;). E.g.:

      "some-graphics.lib";"some-window.lib";"some-system.lib";"open-some32.lib";"some-32.lib";%(AdditionalDependencies)

      или так:

      "..\..\x64\Release\LinearMath.lib"
  1. Указать каждый .lib файл эдиножды, желательно в главном/первом файле программы, с помощью директивы препроцессора #pragma. E.g.:
    #pragma comment(lib, "some.lib")
    #pragma comment(lib, "foo.lib")

Можно использовать сразу два способа.

Я рекомендую использовать второй вариант, когда все подключения пишутся непосредственно в коде. Так нагляднее и переносимость кода увеличивается, когда всё, что нужно написано в самом коде, а не где-то там в настройках IDE.

Файлы библиотек (.dll)

Файлы динамических библиотек (.dll), обычно, находятся в папке «bin» в любой библиотеке.
Путь к файлам динамических библиотек .dll нигде не укажешь. Файлы .dll надо класть в соответсвующие папки IDE или ОС, но легче и лучше всего положить в папку с самим исполняемым файлом программы/приложения.

Параметры конфигурации препроцессора

Также не забывайте указывать параметры конфигурации препроцессора тут: Главное меню > Проект > Свойства проекта > Свойства конфигурации > C/C++ > Препроцессор > Определения препроцессора. Параметры являются комбинированием в определённой последовательности определённых литералов. Вот некоторые из них:

  • Static — статичесий (для статических библиотек — .lib в Win),
  • Dynamic — динамический (для динамических библиотек — .dll в Win),
  • Release — релизная версия сборки,
  • Debug — отладочная версия сборки,
  • MT — многопоточная, MT от слов multi thread
  • MTd — multi thread, debug
  • MD — многопоточный динамический (DLL)

Некоторые возможные варианты параметров:

  • MT_StaticRelease
  • MTd_StaticDebug
  • MD_DynamicRelease

Это далеко не все возможные параметры.

Эти параметры конфигурации препроцессора должны быть обязательно одинаковыми у всех используемых в проекте библиотек, иначе будет ошибка «Error LNK2038: несоответствие значений параметров конфигурации препроцессора» в объектных (.obj) файлах.

Примечания

Пути

Пути директории указывать без конечного слеша.

Опция Компоновщик

Когда проект представляет собой библиотеку, а не исполняемый файл, то опции Компоновщик нет. Это не потому, что для проектов типа «библиотека» указывать директории подключения др. библиотек не нужно и нельзя. Несмотря на то, что опции Компоновщик нет, директории библиотек указываются не только для проектов исполняемых файлов, а также и для библиотек. В этом случае вместо Компоновщика имеется опция Библиотекарь с примерно таким же функционалом.

Библиотеки

При запуске библиотек (файлы .dll и .lib) всегда будет выскакивать окно «с ошибкой» о том, что нельзя запустить этот файл и далее следует его точный путь. Это нормально т.к. библиотеки не запускаются в отличие от исполняемых файлов (.exe).

Заключение

На самом деле, подключать сразу столько всего зачастую не нужно. Как правило, предоставляется только исходный код и всё. Приходится самостоятельно из исходников компилировать библиотеки (файлы .dll и .lib). Т.е. нужно будет указать только заголовочные файлы .h, которые являются частью исходников.

В конце не забудьте пересобрать решение, т.е. очистить и собрать заново.