动态链接库(Dynamic Link Library,缩写为 DLL)是可执行程序在执行的过程中可以动态调用其中函数的函数库,与静态库的不同之处在于,静态库会在程序编译链接的过程中编译到可执行文件中,而程序的执行无需依赖静态库,静态库在windows和linux下的后缀分别为.lib和.a,而动态库在程序编译链接的过程中不会编译链接到可执行文件中,程序需要依赖动态库才能正常运行,否则会导致缺失动态库退出,动态库在windows和linux下的后缀分别为.dll和.so。
1.动态库的建立和编译
我们现在要在Qt上面建立并得到一个共享库myLabel.dll,然后再新建一个工程myWidgetTest来对共享库进行测试。myLabel.dll公共继承自Qlabel,测试为新建一个myLabel类,然后显示一个字符串“Hello World !”。
共享库的建立、编译
(1)Ctrl+N新建,选择其他项目::C++库。
(2)选择共享库
(3)因为继承自QLabel所以要用到QtGui模块。
(4)代码分析
上面步骤完成后,会自动生成一个myLabel_global.h文件,内容如下:
<pre name="code" class="cpp">#ifndef MYLABEL_GLOBAL_H
#define MYLABEL_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYLABEL_LIBRARY)
# define MYLABELSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYLABELSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYLABEL_GLOBAL_H
其中MYLABELSHARED_EXPORT这个宏是将这个程序内容进行输出,等下会用到,这个文件不用改。
myLabel类头文件改为:
#ifndef MYLABEL_H
#define MYLABEL_H
#include "myLabel_global.h"
#include <QLabel> //包含QLabel头文件
class MYLABELSHARED_EXPORT MyLabel:public QLabel {//公共继承自QLabel
public:
MyLabel(QWidget *parent=0);//QWidget *父类默认为0
};
#endif // MYLABEL_H
myLabel类源文件改为:
#include "mylabel.h"
MyLabel::MyLabel(QWidget *parent)
:QLabel(parent)
{
}
现在进行编译,这里选择debug模式进行编译(也可以选择release)。【1】
编译完成后在构建目录的debug目录下可以得打myLabel.dll文件(linux中为myLabel.so)。
2.共享库的测试:
(1)新建一个空的Qt工程。
(2)将myLabel.dll文件拷贝到构建目录下的debug目录下【2】,在工程目录下新建一个mywidget的目录,将两个头文件拷贝到这个目录下。
(3)项目文件做如下改动(注意这里用的是相对路径,头文件的当前目录为工程目录,而LIBS文件的当前目录为构建目录!)
#头文件当前位置为工程目录
INCLUDEPATH += mywidget
#LIBS文件当前位置为构建目录
LIBS += debug/myLabel.dll
SOURCES += \
myWidgetTest.cpp
(4)主程序
#include <QtGui/QApplication>
#include "mylabel.h" //自定义共享库头文件
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
myLabel label;//自定义共享库中的类
label.resize(50,30);
label.setText(QString("Hello World !"));
label.show();
return a.exec();
}
(5)因为共享库是用的debug模式进行编译,所以这里也要选用debug模式进行编译,编译后运行,结果如下:
3.注意事项和错误分析:
【1】共享库和测试程序采用的编译方式要一样,要么都是debug,要么都是release,否则运行的时候会报段错误。
【2】这里把myLabel.dll拷贝到和可执行文件一个目录下,所以可以直接运行。需要注意的是我们在项目文件中指定的那个路径是给编译器的,而不是给系统的,如果指定的目录不是可执行文件的目录,那么编译可以通过,但是运行程序会报错退出:
以上为可执行程序执行的时候缺失依赖库。还有种解决方式是把你的.dll目录加入环境变量中。
【3】如果共享库的头文件发生了改动,而.dll文件没有更新替换,那么运行无疑也是会报错的:(这里的错误代码跟上面的不一样!)