最近在做一个Qt的应用,遇到了DLL导出的问题。问了度娘,没有找到满意的答案。自己动手尝试了好久,结果成功了。把过程分享出来,供小伙伴们参考。
第一步:创建一个dll的工程,关键步骤如图:
应用程序类型选择“DLL”,附加选项选择“空项目”:
开始种植代码:
文件:myWidget.hpp
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QtGui/QWidget>
//该头文件包含了Qt的导入导出宏
#include <QtCore/qglobal.h>
#定义导入导出宏的控制宏和自定义宏CWJ_EXPORT_DLL
#ifdef CWJ_EXPORT
# define CWJ_EXPORT_DLL Q_DECL_EXPORT
#else
# define CWJ_EXPORT_DLL Q_DECL_IMPORT
#endif
class QPushButton;
namespace cwj
{
// 此处使用了自定义的导入导出宏CWJ_EXPORT_DLL
class CWJ_EXPORT_DLL CMyWidget : public QWidget
{
Q_OBJECT
public:
explicit CMyWidget( QWidget * parent = 0, Qt::WindowFlags f = 0);
~CMyWidget();
private slots:
void onBtnClick();
private:
QPushButton *m_btn;
};
}
#endif //MYWIDGET_H
文件myWidget.cpp实现和普通的类实现一样,不需要添加导入导出控制宏和自定义的宏,在此略去。
***********************************************************************************************************************************************************************************
种植完代码,接下来就是工程配置了。
首先,配置导入导出控制宏开关,在配置的时候,可以删除VS自动生成的"工程名_expor"t宏。如图:
接下来,使用配置头文件使用Qt的moc工具生成的自定义生成规则。
(说明:在配置自定义规则的时候,选择了“自定义生成工具”之后,再选择“应用”。这时才会切换到“常规”窗口)如图:
配置完毕之后,在文件上右键,选择“编译”,生成moc文件,然后将moc文件添加到工程中。
好了,最后就是附加库目录和包含文件目录的配置了,不会的请参考前一篇“环境搭建”的博文。
-------------------------------------------------------------------------------------华丽的分割线--------------------------------------------------------------------------------------
使用DLL:
MainWindow工程中的mainWindow.cpp文件源码如下:
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
//包含DLL的头文件
#include "../Dll/myWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow m;
//使用DLL中的类
cwj::CMyWidget myWidget(&m);
m.setCentralWidget(&myWidget);
m.show();
return app.exec();
}
在主应用程序中配置预处理宏CWJ_EXPORT,配置附加的库目录,库文件:
此时编译MainWindow会在链接的时候报错,类似如下(XXXstaticMetaObjec(XXXX)无法解析标准的无法解析Q_OBJECT导致的错误):
1>Link:
1> 正在创建库 D:\My_Step\Qt\ForExportDll\Debug\MainWindow.lib 和对象D:\My_Step\Qt\ForExportDll\Debug\MainWindow.exp
1>mainWindow.obj : error LNK2001: 无法解析的外部符号"public: static struct QMetaObject constcwj::CMyWidget::staticMetaObject" (?staticMetaObject@CMyWidget@cwj@@2UQMetaObject@@B)
1>mainWindow.obj : error LNK2019: 无法解析的外部符号"public: __thiscall cwj::CMyWidget::CMyWidget(class QWidget *,classQFlags<enum Qt::WindowType>)"(??0CMyWidget@cwj@@QAE@PAVQWidget@@V?$QFlags@W4WindowType@Qt@@@@@Z),该符号在函数"public: void __thiscall cwj::CMyWidget::`default constructorclosure'(void)" (??_FCMyWidget@cwj@@QAEXXZ) 中被引用
1>mainWindow.obj : error LNK2019: 无法解析的外部符号"public: virtual __thiscall cwj::CMyWidget::~CMyWidget(void)"(??1CMyWidget@cwj@@UAE@XZ),该符号在函数 _main 中被引用
1>D:\My_Step\Qt\ForExportDll\Debug\MainWindow.exe: fatal error LNK1120: 3 个无法解析的外部命令
原因是:MainWindow中无法解析dll的头文件中Q_OBJECT宏导致的错误。解决办法:将dll工程的moc文件添加到MainWindow工程中。
如图:
OK,运行结果如下: