How to create a library with Qt and use it in an application/ru: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
(fix a lot of ''' that was insted of *)
 
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:
'''Русский''' [[How_to_create_a_library_with_Qt_and_use_it_in_an_application|English]] [[How_to_create_a_library_with_Qt_and_use_it_in_an_application_Spanish|Español]]<br />[[Category:HowTo]]<br />[[Category:Developing_with_Qt::General]]<br />[[Category:Tutorial]]
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
 
'''Русский''' [[How_to_create_a_library_with_Qt_and_use_it_in_an_application|English]] [[How_to_create_a_library_with_Qt_and_use_it_in_an_application_Spanish|Español]]
[[Category:HowTo]]
[[Category:Developing_with_Qt::General]]
[[Category:Tutorial]]


[toc align_right=&quot;yes&amp;quot; depth=&quot;2&amp;quot;]


= Введение =
= Введение =


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


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


При создании совместно используемой библиотеки, которую бы вы хотели присоединить, необходимо удостовериться, что символы, которые будут использованы за пределами библиотеки, будут должным образом экспортироваться после создания библиотеки. В последствии они будут импортированы при присоединении. Это может быть сделано, с помощбю &quot;Q_DECL_EXPORT &quot;:http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_EXPORT и &quot;Q_DECL_IMPORT&amp;quot;:http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_IMPORT как показано в следующем примере:
При создании совместно используемой библиотеки, которую вы бы хотели присоединить, необходимо удостовериться, что символы, которые будут использованы за пределами библиотеки, будут должным образом экспортироваться после создания библиотеки. Впоследствии они будут импортированы при присоединении. Это может быть сделано с помощью [http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_EXPORT Q_DECL_EXPORT ] и [http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_IMPORT Q_DECL_IMPORT] как показано в следующем примере:
 
'''test.h'''
<code>
#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();
};
 
</code>
 
'''test.cpp'''
<code>
#include <QtGui>
#include "test.h"
 
Widget::Widget() : QWidget()
{}
</code>
 
'''test.pro'''
<code>TEMPLATE = lib
# Input
SOURCES += test.cpp
HEADERS += test.h
DEFINES += TEST</code>
 
См. также документацию описывающую [http://doc.qt.io/qt-4.8/sharedlibrary.html Создание Совместно используемых Библиотек].
 
=== Присоединение разделяемой библиотеки к приложению ===
Чтобы использовать разделяемую библиотеку в приложении, вы можете включить ее заголовок в ваш код и использовать доступные методы. Скомпилируйте и соберите с.lib файл. Во время выполнения будет загружена dll, у которой имеется реализация.
 
Для успешной сборки, в файле .pro необходимо сообщить приложению, где найти заголовки и библиотеки. [http://doc.qt.io/qt-4.8/qmake-variable-reference.html#includepath INCLUDEPATH] должен указывать на каталог, где находятся заголовки, и [http://doc.qt.io/qt-4.8/qmake-variable-reference.html#libs LIBS] переменная должна указывать на каталог с .lib файлом. Кроме того, необходимо удостовериться, что .dll будет находиться в указанном месте или помещена в каталог приложения или путь к ней описан в переменной PATH.
 
Для примера:
 
'''loadTestLib.pro'''
<code>
TEMPLATE = app
TARGET =
DEPENDPATH += . ../testLib
INCLUDEPATH += ../testLib
LIBS += -L../testLib/debug -ltestLib
# Input
SOURCES += main.cpp
</code>
 
'''main.cpp'''
<code>
#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();
}


'''test.h'''<br /><code><br />#include &lt;QtGui&amp;gt;


#if defined TEST<br />#define TEST_COMMON_DLLSPEC Q_DECL_EXPORT<br />#else<br />#define TEST_COMMON_DLLSPEC Q_DECL_IMPORT<br />#endif
</code>


class TEST_COMMON_DLLSPEC Widget : public QWidget<br />{<br /> Q_OBJECT<br />public:<br /> Widget();<br />};
=== Использование QLibrary, для загрузки разделяемых библиотек ===
[http://doc.qt.io/qt-4.8/qlibrary.html#details QLibrary] может использоваться для загрузки разделяемых библиотек в момент выполнения. В этом случае достаточно иметь доступ только к .dll, доступ к заголовкам и .lib файлу(ам) не требуется.


Следующий пример показывает, как установить библиотеку для использования с QLibrary. Для разрешения имен функций, они должны быть экспортированы из библиотеки как C функции (т.е. без искажения имени). Это означает, что функции должны быть обернуты в блок extern "C", в случае если библиотека скомпилирована компилятором C.
Вот как делается это на Windows, также необходимо явно экспортировать функцию для использования DLL [http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_EXPORT Q_DECL_EXPORT] и [http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_IMPORT Q_DECL_IMPORT]
'''qlibraryLibrary.pro'''
<code>
TEMPLATE = lib
HEADERS += widget.h
SOURCES += widget.cpp
DEFINES += TEST
</code>
</code>


'''test.cpp'''<br /><code><br />#include &lt;QtGui&amp;gt;<br />#include &quot;test.h&amp;quot;
'''widget.h'''
<code>
#include <QtGui>


Widget::Widget() : QWidget()<br />{}<br /></code>
#if defined TEST
#define TEST_COMMON_DLLSPEC Q_DECL_EXPORT
#else
#define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
#endif


'''test.pro'''<br /><code>TEMPLATE = lib<br /># Input<br />SOURCES ''= test.cpp<br />HEADERS''= test.h<br />DEFINES ''= TEST</code>
extern "C" TEST_COMMON_DLLSPEC QWidget* createWidget1();
<br />См. также документацию описывающую &quot;Создание Совместно используемых Библиотек&amp;quot;:http://doc.qt.io/qt-4.8/sharedlibrary.html.
<br />h3. Присоединение разделяемой библиотеки к приложению
<br />Чтобы использовать разделяемую библиотеку в приложении, вы можете включить ее заголовок в ваш код и использовать доступные методы. Скомпилируйте и соберите с.lib файл. Во время выполнения будет загружена dll, у которой имеется реализация.
<br />Для успешной сборки, в файле .pro необходимо сообщить приложению, где найти заголовки и библиотеки. &quot;INCLUDEPATH&amp;quot;:http://doc.qt.io/qt-4.8/qmake-variable-reference.html#includepath должен указывать на каталог, где находятся заголовки, и &quot;LIBS&amp;quot;:http://doc.qt.io/qt-4.8/qmake-variable-reference.html#libs переменная должна указывать на каталог с .lib файлом. Кроме того, необходимо удостовериться, что .dll будет находиться в указанном месте или помещена в каталог приложения или путь к ней описан в переменной PATH.
<br />Для примера:
<br />'''loadTestLib.pro'''<br /><code><br />TEMPLATE = app<br />TARGET =<br />DEPENDPATH''= . ../testLib<br />INCLUDEPATH ''= ../testLib<br />LIBS''= -L../testLib/debug <s>ltestLib<br /># Input<br />SOURCES ''= main.cpp<br /></code>
<br />'''main.cpp'''<br /><code><br />#include &lt;QtGui&amp;gt;<br />#include &quot;test.h&amp;quot;
<br />int main(int argc, char *argv[])<br />{<br /> QApplication a(argc, argv);<br /> Widget w;<br /> w.resize(100,100);<br /> w.show();<br /> return a.exec&amp;amp;#40;&amp;#41;;<br />}


<br /></code>
</code>
<br />h3. Использование QLibrary, для загрузки разделяемых библиотек
 
<br />&quot;QLibrary&amp;quot;:http://doc.qt.io/qt-4.8/qlibrary.html#details может использоваться для загрузки разделяемых библиотек в момент выполнения. В этом случае достаточно иметь доступ только к .dll, доступ к заголовкам и .lib файлу(ам) не требуется.
'''widget.cpp'''
<br />Следующий пример показывает, как установить библиотеку для использования с QLibrary. Для разрешения имен функций, они должны быть экспортированы из библиотеки как C функции (т.е. без искажения имени). Это означает, что функции должны быть обернуты в блок extern &quot;C&amp;quot;, в случае если библиотека скомпилирована компилятором C.
<code>
<br />Вот как делается это на Windows, также необходимо явно экспортировать функцию для использования DLL &quot;Q_DECL_EXPORT&amp;quot;:http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_EXPORT и &quot;Q_DECL_IMPORT&amp;quot;:http://doc.qt.io/qt-4.8/qtglobal.html#Q_DECL_IMPORT
#include <QtGui>
<br />'''qlibraryLibrary.pro'''<br /><code><br />TEMPLATE = lib<br />HEADERS''= widget.h<br />SOURCES ''= widget.cpp<br />DEFINES''= TEST<br /></code>
#include "widget.h"
<br />'''widget.h'''<br /><code><br />#include &lt;QtGui&amp;gt;
 
<br />#if defined TEST<br />#define TEST_COMMON_DLLSPEC Q_DECL_EXPORT<br />#else<br />#define TEST_COMMON_DLLSPEC Q_DECL_IMPORT<br />#endif
QWidget* createWidget1()
<br />extern &quot;C&amp;quot; TEST_COMMON_DLLSPEC QWidget* createWidget1();
{
<br /></code>
QWidget *wid = new QWidget();
<br />'''widget.cpp'''<br /><code><br />#include &lt;QtGui&amp;gt;<br />#include &quot;widget.h&amp;quot;
wid->resize(100,100);
<br />QWidget* createWidget1()<br />{<br /> QWidget '''wid = new QWidget();<br /> wid-&gt;resize(100,100);<br /> return wid;<br />}
return wid;
<br /></code>
}
<br />h3. Загрузка библиотеки, используя QLibrary
 
<br />Чтобы загрузить библиотеку, используя QLibrary, можете просто передать .dll в конструктор QLibrary. Удостоверьтесь, что .dll доступна в каталоге приложения или в переменной PATH. Для того чтобы воспользоваться функциями библиотеки в приложении, вы должны разрешить их использование &quot;QLibrary::resolve()&quot;:http://doc.qt.io/qt-4.8/qlibrary.html#resolve.
</code>
<br />Следующий пример загружает выше-созданную библиотеку, и использует одну из ее функций, для создания и отображения виджета.
 
<br /><code><br />#include &lt;QtGui&amp;gt;
=== Загрузка библиотеки, используя QLibrary ===
<br />int main(int argc, charargv)<br />{<br /> QApplication app(argc, argv);<br /> QLibrary library(&quot;qlibraryLibrary.dll&amp;quot;);<br /> if (!library.load())<br /> qDebug() &lt;&lt; library.errorString();<br /> if (library.load())<br /> qDebug() &lt;&lt; &quot;library loaded&amp;quot;;
Чтобы загрузить библиотеку, используя QLibrary, можете просто передать .dll в конструктор QLibrary. Удостоверьтесь, что .dll доступна в каталоге приложения или в переменной PATH. Для того чтобы воспользоваться функциями библиотеки в приложении, вы должны разрешить их использование [http://doc.qt.io/qt-4.8/qlibrary.html#resolve QLibrary::resolve()].
<br /> typedef QWidget'''('''CreateWidgetFunction)(void);<br /> CreateWidgetFunction cwf = (CreateWidgetFunction)library.resolve(&quot;createWidget1&amp;quot;);<br /> if (cwf) {<br /> QWidget''' wid = cwf();<br /> if (wid)<br /> wid</s>&gt;show();<br /> } else {<br /> qDebug() &lt;&lt; &quot;Could not show widget from the loaded library&amp;quot;;<br /> }<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
 
Следующий пример загружает выше-созданную библиотеку, и использует одну из ее функций для создания и отображения виджета.
 
<code>
#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();
}
</code>


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


При создании статической библиотеки необходимо определить опцию staticlib &quot;CONFIG &quot;:http://doc.qt.io/qt-4.8/qmake-variable-reference.html#config в .pro файле. В отличие от примера разделяемой библиотеки, в .h файле не требуется устанавливать никаких специальных символов для экспорта и импорта, потому как библиотека будет встроена в приложение, например:
При создании статической библиотеки необходимо определить опцию staticlib [http://doc.qt.io/qt-4.8/qmake-variable-reference.html#config CONFIG ] в .pro файле. В отличие от примера разделяемой библиотеки, в .h файле не требуется устанавливать никаких специальных символов для экспорта и импорта, потому как библиотека будет встроена в приложение, например:


'''test.pro'''<br /><code><br />TEMPLATE = lib<br />CONFIG+= staticlib<br /># Input<br />HEADERS ''= test.h<br />SOURCES''= test.cpp<br /></code>
'''test.pro'''
<code>
TEMPLATE = lib
CONFIG+= staticlib
# Input
HEADERS += test.h
SOURCES += test.cpp
</code>


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


Подобно тому, как мы сделали это при загрузке разделяемой библиотеки, необходимо описать &quot;INCLUDEPATH&amp;quot;:http://doc.qt.io/qt-4.8/qmake-variable-reference.html#includepath, чтобы указать на каталог, где установлены заголовки и &quot;LIBS&amp;quot;:http://doc.qt.io/qt-4.8/qmake-variable-reference.html#libs переменную, чтобы указать на .lib файл, например:
Подобно тому, как мы сделали это при загрузке разделяемой библиотеки, необходимо описать [http://doc.qt.io/qt-4.8/qmake-variable-reference.html#includepath INCLUDEPATH], чтобы указать на каталог, где установлены заголовки и [http://doc.qt.io/qt-4.8/qmake-variable-reference.html#libs LIBS] переменную, чтобы указать на .lib файл, например:


'''useStaticLib.pro'''<br /><code><br />TEMPLATE = app<br />TARGET =<br />CONFIG+= console<br /># Input<br />SOURCES ''= main.cpp<br />INCLUDEPATH''= ../staticLibrary<br />LIBS+= -L../staticLibrary/debug -lstaticLibrary
'''useStaticLib.pro'''
<code>
TEMPLATE = app
TARGET =
CONFIG+= console
# Input
SOURCES += main.cpp
INCLUDEPATH += ../staticLibrary
LIBS+= -L../staticLibrary/debug -lstaticLibrary


</code>
</code>


'''main.cpp'''<br /><code><br />#include &lt;QtGui&amp;gt;<br />#include &quot;test.h&amp;quot;
'''main.cpp'''
<code>
#include <QtGui>
#include "test.h"


int main(int argc, char *argv[])<br />{<br /> QApplication a(argc, argv);<br /> Widget w;<br /> w.resize(100,100);<br /> w.show();<br /> return a.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.resize(100,100);
w.show();
return a.exec();
}
</code>


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

Latest revision as of 13:03, 4 January 2017

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.

Русский English Español


Введение

Это руководство иллюстрирует разные подходы к созданию и применению пользовательских библиотек в приложении на 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 -ваш выбор. Недостаток в том, что при отсутствии разделяемой библиотеки в системе приложение работать не будет.

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