最近在做一个Qt的应用,遇到了DLL导出的问题。问了度娘,没有找到满意的答案。自己动手尝试了好久,结果成功了。把过程分享出来,供小伙伴们参考。

第一步:创建一个dll的工程,关键步骤如图:

应用程序类型选择“DLL”,附加选项选择“空项目”:

android qt 动态库打包 qt动态库的导出_vs

开始种植代码:

文件: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宏。如图:

android qt 动态库打包 qt动态库的导出_Qt_02


接下来,使用配置头文件使用Qt的moc工具生成的自定义生成规则。

(说明:在配置自定义规则的时候,选择了“自定义生成工具”之后,再选择“应用”。这时才会切换到“常规”窗口)如图:

android qt 动态库打包 qt动态库的导出_android qt 动态库打包_03

android qt 动态库打包 qt动态库的导出_android qt 动态库打包_04

配置完毕之后,在文件上右键,选择“编译”,生成moc文件,然后将moc文件添加到工程中。

android qt 动态库打包 qt动态库的导出_android qt 动态库打包_05

好了,最后就是附加库目录和包含文件目录的配置了,不会的请参考前一篇“环境搭建”的博文。

-------------------------------------------------------------------------------------华丽的分割线--------------------------------------------------------------------------------------

使用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,配置附加的库目录,库文件:

android qt 动态库打包 qt动态库的导出_qt_06


此时编译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工程中。

如图:

android qt 动态库打包 qt动态库的导出_android qt 动态库打包_07

OK,运行结果如下:

android qt 动态库打包 qt动态库的导出_dll DLL 动态链接库 使用_08