How to create a library with Qt and use it in an application/ru
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine. Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean. |
Введение
Это руководство иллюстрирует разные подходы к созданию и применению пользовательских библиотек в приложении на Windows. Первая часть объясняет, как создать совместно используемую библиотеку и как присоединить ее к приложению. Вторая часть - о создании и использовании статической библиотеки.
Создание разделяемой библиотеки
При создании совместно используемой библиотеки, которую вы бы хотели присоединить, необходимо удостовериться, что символы, которые будут использованы за пределами библиотеки, будут должным образом экспортироваться после создания библиотеки. Впоследствии они будут импортированы при присоединении. Это может быть сделано с помощью Q_DECL_EXPORT и Q_DECL_IMPORT как показано в следующем примере:
test.h
#include <QtGui>
#if defined TEST
#define TEST_COMMON_DLLSPEC Q_DECL_EXPORT
#else
#define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
#endif
class TEST_COMMON_DLLSPEC Widget : public QWidget
{
Q_OBJECT
public:
Widget();
};
test.cpp
#include <QtGui>
#include "test.h"
Widget::Widget() : QWidget()
{}
test.pro
TEMPLATE = lib
# Input
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
# Input
SOURCES += main.cpp
main.cpp
#include <QtGui>
#include "test.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.resize(100,100);
w.show();
return a.exec();
}
Использование 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
widget.h
#include <QtGui>
#if defined TEST
#define TEST_COMMON_DLLSPEC Q_DECL_EXPORT
#else
#define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
#endif
extern "C" TEST_COMMON_DLLSPEC QWidget* createWidget1();
widget.cpp
#include <QtGui>
#include "widget.h"
QWidget* createWidget1()
{
QWidget *wid = new QWidget();
wid->resize(100,100);
return wid;
}
Загрузка библиотеки, используя QLibrary
Чтобы загрузить библиотеку, используя QLibrary, можете просто передать .dll в конструктор QLibrary. Удостоверьтесь, что .dll доступна в каталоге приложения или в переменной PATH. Для того чтобы воспользоваться функциями библиотеки в приложении, вы должны разрешить их использование QLibrary::resolve().
Следующий пример загружает выше-созданную библиотеку, и использует одну из ее функций для создания и отображения виджета.
#include <QtGui>
int main(int argc, charargv)
{
QApplication app(argc, argv);
QLibrary library("qlibraryLibrary.dll");
if (!library.load())
qDebug() << library.errorString();
if (library.load())
qDebug() << "library loaded";
typedef QWidget *(*CreateWidgetFunction)(void);
CreateWidgetFunction cwf = (CreateWidgetFunction)library.resolve("createWidget1");
if (cwf) {
QWidget* wid = cwf();
if (wid)
wid->show();
} else {
qDebug() << "Could not show widget from the loaded library";
}
return app.exec();
}
Создание статической библиотеки
При создании статической библиотеки необходимо определить опцию staticlib CONFIG в .pro файле. В отличие от примера разделяемой библиотеки, в .h файле не требуется устанавливать никаких специальных символов для экспорта и импорта, потому как библиотека будет встроена в приложение, например:
test.pro
TEMPLATE = lib
CONFIG+= staticlib
# Input
HEADERS += test.h
SOURCES += test.cpp
Использование статической библиотеки в приложении
Подобно тому, как мы сделали это при загрузке разделяемой библиотеки, необходимо описать INCLUDEPATH, чтобы указать на каталог, где установлены заголовки и LIBS переменную, чтобы указать на .lib файл, например:
useStaticLib.pro
TEMPLATE = app
TARGET =
CONFIG+= console
# Input
SOURCES += main.cpp
INCLUDEPATH += ../staticLibrary
LIBS+= -L../staticLibrary/debug -lstaticLibrary
main.cpp
#include <QtGui>
#include "test.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.resize(100,100);
w.show();
return a.exec();
}
Какой подход выбрать
Принятие решения о том, какой подход выбрать, зависит от Ваших потребностей.
При создании разделяемой библиотеки потребуется установить ее в целевой системе вместе с приложением. Преимущество: приложения собранные на разделяемых библиотеках, маленькие. Это независит от того, что используется для загрузки .dll, QLibrary или просто стандартное подключение. Важно, имеете ли вы доступ к заголовочным и .lib файлам или нет. Если доступа не имеете, тогда QLibrary -ваш выбор. Недостаток в том, что при отсутствии разделяемой библиотеки в системе приложение работать не будет.
Статическое подключение позволяет создать автономно исполняемую программу. Преимущество состоит в том, что для работы программы вам необходимо будет установить только несколько файлов. Недостаток в том, что исполняемые программы большие.