Qt подключение библиотек linux

Обновлено: 07.07.2024

Подробное объяснение создания и связывания разделяемых библиотек в Qt под Linux

Нажмите на синий текст выше, чтобы подписаться на официальный аккаунт, который удобно читать и связываться в следующий раз

По мере написания более или менее программ мы будем более или менее использовать библиотеки, написанные другими; или мы не хотим, чтобы другие видели некоторые из наших основных программ, мы можем инкапсулировать основные программы в библиотеки. На этот раз я поделюсь с вами методом использования Qt для создания разделяемых библиотек в Ubuntu и связывания разделяемых библиотек в Qt.

Общая библиотека называется под Linux, а под Windows - динамической библиотекой. Все должны понимать, что библиотека, используемая программой во время компиляции, и библиотека, используемая программой во время выполнения, должны быть согласованы, иначе программа может вылететь. И если путь к библиотеке времени выполнения не задан, система будет искать по пути по умолчанию, и если программа не найдена, она зависнет. В следующих статьях будут подведены итоги и даны пояснения.

Программная платформа: Ubuntu14.04, Qt5.5.1

Во-первых, Qt создает общую библиотеку

1. Создайте проект Qt библиотеки типов.

① Новый проект -> Библиотека -> Библиотека C ++:

640?wx_fmt=png

②Введите выберите общую библиотеку по умолчанию, введите имя и выберите путь к проекту. Проще говоря, типы библиотек - это динамические библиотеки, статические библиотеки и плагины Qt.

640?wx_fmt=png

③Выберите пакет по умолчанию

④Выберите нужный модуль, здесь ни одного модуля не проверял

640?wx_fmt=png

⑤Основная информация о настройке

2. Инженерная документация.

①После создания проекта некоторые файлы, созданные Qt, удаляются. Каталог файлов выглядит следующим образом

640?wx_fmt=png

② Измените файл .pro, добавьте настройку номера версии и т. Д.

ЦЕЛЬ: имя библиотеки.

ШАБЛОН: тип шаблона, тип - lib, то есть создается файл библиотеки

ВЕРСИЯ (новая часть): установка номера версии библиотеки

CONFIG (новая часть): управление именами версий скомпилированных библиотек Debug и Release

1. Создайте общую библиотеку

В этой разделяемой библиотеке реализована функция вычисления суммы двух целых чисел. Это слишком просто, не обращайте внимания

① содержимое файла .h

Если вы просто создадите, общая библиотека будет сгенерирована напрямую, и если вы запустите ее, она будет выглядеть так.

640?wx_fmt=png

④Создайте эффекты динамической библиотеки

На этом этапе мы создали динамическую библиотеку, вы можете увидеть номер версии добавленной нами динамической библиотеки.

Обратите внимание, что здесь я не делал различий между версиями Debug и Release.

640?wx_fmt=png

Два, связать динамическую библиотеку

1. Создайте файлы дополнения к проекту.

После создания приложения, наследующего QWidget, добавьте файл, организованный в следующем каталоге в каталоге того же уровня, что и файл .pro:

2. Добавить библиотеку с Qt

① Щелкните проект правой кнопкой мыши -> добавить библиотеку

640?wx_fmt=png

②Выберите тип библиотеки ссылок, выберите [Внешняя библиотека]

640?wx_fmt=png

③Выберите путь и платформу библиотеки ссылок и другой информации

640?wx_fmt=png

④ Новые файлы в .pro

unix:!macx: LIBS += -L$$PWD/Lib/test/linux_x32/lib/ -lTestLib

$$ PWD: используется для указания полного пути к каталогу, содержащему файл .pro

LIBS: укажите список библиотек, связанных с проектом.

⑤ Модифицированный файл .pro

В реальных проектах наша библиотека может использовать несколько платформ, поэтому обычно создается следующим образом

3. Подготовка тестовой программы.

③Функция программы и эффект от работы

Пользовательский интерфейс введите два числа, нажмите кнопку и вычислите через общую библиотеку следующим образом:

640?wx_fmt=png

три. Резюме постскриптума

1. Проблемы и решения с использованием разделяемых библиотек

Когда я раньше использовал общий доступ, я сообщал об ошибке вроде этого:

error while loading shared libraries: libTestLib.so.1: cannot open shared object file: No such file or directory

Не удалось загрузить общую библиотеку, не найдено. На тот момент решением было скопировать разделяемую библиотеку в usr / local / lib, чтобы проблема исчезла.После копирования используйте команду ldconfig.

Вышеупомянутая ошибка заключается в том, что разделяемая библиотека не обнаруживается во время выполнения. В Linux вы можете использовать команду ldd для просмотра библиотек, необходимых для исполняемой программы. Эффект будет следующим:

640?wx_fmt=png

2. Почему вышеупомянутая ошибка не отображается при запуске в Qt?

Поэтому я использовал команду locate + имя библиотеки для поиска, но я не нашел разделяемую библиотеку, только что созданную по другим путям; поэтому я пошел искать файл, который настраивает переменные среды Linux, и не нашел его. Под root проверьте файл /etc/ld.so.conf.d.

Однако я не сдался, поэтому я использовал Google для поиска связанных вопросов [процесс компиляции Qt]. Хотя я не нашел ответа, я нашел некоторые подсказки:

640?wx_fmt=png

В значении, соответствующем LD_LIBRARY_PATH в разделе «Среда выполнения в проектах», я увидел каталог библиотеки ссылок в программе. На данный момент, думаю, я нашел причину.

3. Резюме в резюме

Решая проблему, мы узнаем много других знаний по пути. Как и в этот раз, я знаю сценарии использования нескольких команд Linux.

Это руководство иллюстрирует разные подходы к созданию и применению пользовательских библиотек в приложении на Windows. Первая часть объясняет, как создать совместно используемую библиотеку и как присоединить ее к приложению. Вторая часть - о создании и использовании статической библиотеки.

Создание разделяемой библиотеки

При создании совместно используемой библиотеки, которую вы бы хотели присоединить, необходимо удостовериться, что символы, которые будут использованы за пределами библиотеки, будут должным образом экспортироваться после создания библиотеки. Впоследствии они будут импортированы при присоединении. Это может быть сделано с помощью Q_DECL_EXPORT и Q_DECL_IMPORT как показано в следующем примере:

  1. include <QtGui>
  1. if defined TEST
  2. define TEST_COMMON_DLLSPEC Q_DECL_EXPORT
  3. else
  4. define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
  5. endif

test.pro TEMPLATE = lib

SOURCES += test.cpp HEADERS += test.h DEFINES += TEST

Присоединение разделяемой библиотеки к приложению

Чтобы использовать разделяемую библиотеку в приложении, вы можете включить ее заголовок в ваш код и использовать доступные методы. Скомпилируйте и соберите с.lib файл. Во время выполнения будет загружена dll, у которой имеется реализация.

Для успешной сборки, в файле .pro необходимо сообщить приложению, где найти заголовки и библиотеки. INCLUDEPATH должен указывать на каталог, где находятся заголовки, и LIBS переменная должна указывать на каталог с .lib файлом. Кроме того, необходимо удостовериться, что .dll будет находиться в указанном месте или помещена в каталог приложения или путь к ней описан в переменной PATH.

loadTestLib.pro TEMPLATE = app TARGET = DEPENDPATH += . ../testLib INCLUDEPATH += ../testLib LIBS += -L../testLib/debug -ltestLib

int main(int argc, char *argv[])

Использование QLibrary, для загрузки разделяемых библиотек

QLibrary может использоваться для загрузки разделяемых библиотек в момент выполнения. В этом случае достаточно иметь доступ только к .dll, доступ к заголовкам и .lib файлу(ам) не требуется.

Следующий пример показывает, как установить библиотеку для использования с QLibrary. Для разрешения имен функций, они должны быть экспортированы из библиотеки как C функции (т.е. без искажения имени). Это означает, что функции должны быть обернуты в блок extern "C", в случае если библиотека скомпилирована компилятором C.

Вот как делается это на Windows, также необходимо явно экспортировать функцию для использования DLL Q_DECL_EXPORT и Q_DECL_IMPORT

qlibraryLibrary.pro TEMPLATE = lib HEADERS += widget.h SOURCES += widget.cpp DEFINES += TEST

  1. include <QtGui>
  1. if defined TEST
  2. define TEST_COMMON_DLLSPEC Q_DECL_EXPORT
  3. else
  4. define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
  5. endif

extern "C" TEST_COMMON_DLLSPEC QWidget* createWidget1();

Загрузка библиотеки, используя QLibrary

Чтобы загрузить библиотеку, используя QLibrary, можете просто передать .dll в конструктор QLibrary. Удостоверьтесь, что .dll доступна в каталоге приложения или в переменной PATH. Для того чтобы воспользоваться функциями библиотеки в приложении, вы должны разрешить их использование QLibrary::resolve().

Следующий пример загружает выше-созданную библиотеку, и использует одну из ее функций для создания и отображения виджета.

int main(int argc, charargv)

Создание статической библиотеки

При создании статической библиотеки необходимо определить опцию staticlib CONFIG в .pro файле. В отличие от примера разделяемой библиотеки, в .h файле не требуется устанавливать никаких специальных символов для экспорта и импорта, потому как библиотека будет встроена в приложение, например:

test.pro TEMPLATE = lib CONFIG+= staticlib

HEADERS += test.h SOURCES += test.cpp

Использование статической библиотеки в приложении

Подобно тому, как мы сделали это при загрузке разделяемой библиотеки, необходимо описать INCLUDEPATH, чтобы указать на каталог, где установлены заголовки и LIBS переменную, чтобы указать на .lib файл, например:

useStaticLib.pro TEMPLATE = app TARGET = CONFIG+= console

SOURCES += main.cpp INCLUDEPATH += ../staticLibrary LIBS+= -L../staticLibrary/debug -lstaticLibrary

int main(int argc, char *argv[])

Какой подход выбрать

Принятие решения о том, какой подход выбрать, зависит от Ваших потребностей.

При создании разделяемой библиотеки потребуется установить ее в целевой системе вместе с приложением. Преимущество: приложения собранные на разделяемых библиотеках, маленькие. Это независит от того, что используется для загрузки .dll, QLibrary или просто стандартное подключение. Важно, имеете ли вы доступ к заголовочным и .lib файлам или нет. Если доступа не имеете, тогда QLibrary -ваш выбор. Недостаток в том, что при отсутствии разделяемой библиотеки в системе приложение работать не будет.

Статическое подключение позволяет создать автономно исполняемую программу. Преимущество состоит в том, что для работы программы вам необходимо будет установить только несколько файлов. Недостаток в том, что исполняемые программы большие.

На форуме возник вопрос, как создать динамическую библиотеку и правильно её подключить в сторонний проект. Периодически такие вопросы возникают, поэтому рассмотрим один вариант создание динамической библиотеки dll для Windows с использованием визардов стандартных в Qt Creator.

В данном случае не будет рассматриваться вариант, когда проект разбивается на подпроекты, которые компилируются как библиотеки и потом подключаются в главный проект. Поскольку это будут динамические внутренние библиотеки проекта. Создадим именно внешнюю библиотеку, которую теоретически можно будет распространять в виде бинарников.

Создадим два проекта:

  1. QuiLib - это будет внешняя динамическая библиотека, которая будет содержать одно диалоговое окно. Данное диалоговое окно будет открываться в основном проекте.
  2. WithDynamicLibrary - проект, который будет использоваться как раз для подключения данной динамической библиотеки.

Шаг 1

Выберем в меню Qt Creator создание проекта и выберем тип нашего проекта. Это будет библиотека на C++.


Шаг 2


Шаг 3

Выберем комплекты для сборки проекта.

Здесь имеется очень важный момент, а котором новички могут забывать. Если вы собираете проект с помощью компилятора определённой версии, то и использовать данные библиотеки можно будет только в проекте, который будет собираться компилятором той же версии.

Я собираю данную библиотеку компилятором MSVC2017.


Шаг 4

Выбираем необходимые модули. Для нашей библиотеки хватит базового функционала.


Шаг 5

Дадим название классу библиотеки, который будет в нём использоваться. Название в данном случае будет такое же, как и название самой библиотеки. Но можно и поменять. Это не принципиально.


Шаг 6

Используете систему контроля версий? Так добавьте проект под контроль версий. Если нет, то ничего не делайте. И просто завершите создание библиотеки.


Шаг 7

Посмотрим на файлы проекта и немного модифицируем их.

Структура проекта


QuiLib.pro

В данном файле имеется информация о том, что это именно библиотека. Вот в данной строчке.

Вот полный код pro-файла

quilib_global.h

Хедер для определения дефайнов экспорта в библиотеке. Классы, которые будут помечены дефайном экспорта, будут доступны для использования вне библиотеки.

QuiLib.h

Подкорректируем немного заголовочный файл диалогового окна, нам ведь нужен именно диалог, а значит класс в данном заголовочном файле потребуется наследовать от QDialog.

QuiLib.cpp

Также напишем реализацию конструктора диалогового окна, чтобы он нам сообщил с помощью QLabel, что это диалоговое окно из внешней библиотеки.

Шаг 8

Скомпилируем проект в Debug и Release версиях.

Вот например, что будет в каталоге release сборки библиотеки. Из тех файлов нам понадобятся только файлы QuiLib.dll и QuiLib.lib. Помимо этих файлов нужны ещё будут заголовочный файлы из самого проекта, но об этом немного позднее.


Шаг 9

Создание проекта, который будет использовать эту динамическую библиотеку. Процесс создания будет стандартный, через визард в Qt Creator. Нужно будет выбрать Приложение на Qt.

Как добавить внешнюю библиотеку в проект, построенный Qt Creator RC1 (версия 0.9.2)? Например, функция win32 EnumProcesses() требует Psapi.lib для добавления в проект для сборки.

правильный способ сделать это так:

таким образом, он будет работать на всех платформах, поддерживаемых Qt. Идея заключается в том, что вы должны отделить каталог от имени библиотеки (без расширения и без префикса "lib"). Конечно, если вы включаете конкретный lib для Windows, это действительно не имеет значения.

Если вы хотите сохранить свои файлы lib в каталоге проекта, вы можете ссылаться на них с помощью $$_PRO_FILE_PWD_ переменной, например:

вы используете qmake проектов? Если это так, вы можете добавить внешнюю библиотеку с помощью LIBS переменной. Например:

не будет работать, потому что вы используете пробелы в программные файлы. В этом случае вам нужно добавить кавычки, поэтому результат будет выглядеть так:LIBS += "C:\Program Files\OpenCV\lib". Я рекомендую размещать библиотеки в местах без пробелов; -)

ошибка, которую вы имеете в виду, связана с отсутствием дополнительного пути включения. Попробуйте добавить его с помощью: INCLUDEPATH += C:\path\to\include\files\ Надеюсь, это сработает. С уважением.

и добавить несколько файлов библиотеки вы можете написать, как показано ниже:

INCLUDEPATH *= E:/DebugLibrary/VTK E:/DebugLibrary/VTK/Common E:/DebugLibrary/VTK/Filtering E:/DebugLibrary/VTK/GenericFiltering E:/DebugLibrary/VTK/Graphics E:/DebugLibrary/VTK/GUISupport/Qt E:/DebugLibrary/VTK/Hybrid E:/DebugLibrary/VTK/Imaging E:/DebugLibrary/VTK/IO E:/DebugLibrary/VTK/Parallel E:/DebugLibrary/VTK/Rendering E:/DebugLibrary/VTK/Utilities E:/DebugLibrary/VTK/VolumeRendering E:/DebugLibrary/VTK/Widgets E:/DebugLibrary/VTK/Wrapping

LIBS * = - LE: / DebugLibrary / VTKBin/bin / release -lvtkCommon -lvtksys -lQVTK-lvtkWidgets-lvtkRendering-lvtkGraphics-lvtkImaging-lvtkIO-lvtkFiltering-lvtkDICOMParser-lvtkpng-lvtktiff-lvtkzlib-lvtkjpeg-lvtkexpat-lvtkNetCDF-lvtkexoIIc-lvtkftgl-lvtkfreetype-lvtkHybrid-lvtkVolumeRendering-lvtkfreetype lqvtkwidgetplugin-lvtkgenericfiltering

Если вы хотите развернуть свое приложение на машинах клиентов, а не использовать свое приложение только самостоятельно, мы обнаружим, что LIBS+= -Lxxx -lyyy метод может привести к путанице, если нет проблем.

мы разрабатываем приложения для Linux, Mac и Windows, используя Qt. Мы грузим полные, отдельно стоящие применения. Так что все несистемные библиотеки должны быть включены в пакет развертывания. Мы хотим, чтобы наши клиенты могли запускать приложение с одного USB-накопителя для всех ОС. По причинам из совместимости платформы USB-накопитель должен быть отформатирован как FAT32, который не поддерживает символические ссылки (Linux).

мы нашли LIBS+= -Lxxx -lyyy идиома слишком много "черного ящика":

мы точно не знаем, что такое путь к файлу (статической или динамической) библиотеки, найденной компоновщиком. Это неудобно. Наш Mac linker регулярно находил библиотеки, отличные от тех, которые мы думали, что должны использоваться. Это произошло несколько раз с библиотеками OpenSSL где компоновщик Mac нашел и использовал свою собственную - более старую, несовместимую - версию OpenSSL, а не нашу запрошенную версию.

мы не можем позволить, чтобы компоновщик использовал символические ссылки на библиотеки, поскольку это нарушило бы пакет развертывания.

мы хотим видеть от имя библиотеки, связываем ли мы статическую или динамическую библиотеку.

поэтому для нашего конкретного случая мы используем только абсолютные filepaths и проверьте, существуют ли они. Мы удаляем все ссылки.

Сначала мы узнаем, какую операционную систему мы используем, и помещаем это в переменную CONFIG. И, например, для Linux 64bit, затем:

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

Я хотел бы добавить для полноты, что вы также можете добавить только путь к библиотеке, где он будет искать зависимую библиотеку (на которую может не быть прямой ссылки в вашем коде, но библиотека, которую вы используете, может понадобиться).

для сравнения, это будет соответствовать тому, что делает среда LIBPATH, но ее вид неясен в Qt Creator и не хорошо документирован.

путь, которым я обошел это, следующий:

по сути, если вы не укажите фактическое имя библиотеки, он добавляет путь к тому, где он будет искать зависимые библиотеки. Разница в синтаксисе невелика, но это очень полезно, чтобы указать только путь, где искать зависимые библиотеки. Иногда это просто боль, чтобы предоставить каждому пути отдельную библиотеку, где вы знаете, что все они находятся в определенной папке, и Qt Creator подберет их.

Читайте также: