1 背景知识
九年前,PSE(化学工程,过程系统工程)硕士毕业,由于整个研究生期间均使用Matlab做课题研究,并有幸帮助老师带了2年的Matlab实验课程。毕业那阵,正如我这个课题组的师兄所说,在化工中我的计算机水平是最强的,在计算机中我的化工水平也是最强的。可企业不需要这样的人,便陷入了找工作的尴尬期。找份工作先干着吧,受当时一句话”真正的程序员用C++”的影响,选择了VC++,由于无人指导,大概那个时候认为VC++就是C++吧。
由于第一个月只干了二十几天,到手工资900多点,于是彻底从朋友圈中消失了。为了这个爱好,也只有坚持了。看了N本关于C++的书籍,特别是那边号称Windows编程圣经的MFC C++Windows程序设计。经过几年努力,也用MFC C++弄出个不大不小的系统。虽说小,也具备了串口通信、数据库操作、报表打印等功能。
目前开始使用Qt,总舍不得丢掉MFC,虽然明知道使用Qt调用VS 写的DLL纯属于只是一部分很小的需求。然后走过必留痕迹,就把其记录下来。主要原因如下:
- Qt只能使用MFC导出的标准接口,无法使用MFC导出的类;
- MFC能够使用MFC导出的类;
- Qt能够使用Qt导出的类。
对于企业级应用,MFC应用也好、Qt也罢,若需使用DLL或plugin,如果DLL或plugin不能导出类,那么将失去面向对象的强大功能。想使用面向对象的方法将各模块进行清洗划分,几乎是不可能的。
过去MFC界面框架比较火,现在Qt如日中天,说不定那天又出现的Xt什么之类的框架,若想代码具有较高的可移植性,业务逻辑层代码尽量做到:
- 使用标准的C++语法;
- 使用C++标准库;
- 尽量不用系统级接口,如Win32 API。
- 尽量使用C++提供的技术,如线程技术进行流程管理。
把握了以上原则,业务层代码才可以在跨平台、跨界面框架做到100%重用。废话不说了,步入正题。
2 MFC 工程
本文不讲述如何使用VS解决方案管理工程,本文仅给出工程非默认配置或需要注意的地方。如果对此不熟悉,请参考百度,或跳过该章节,直接阅览感兴趣的部分。
2.1 MFC DLL创建
头文件“MFC_DLL.h”中代码如下:
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the MFC_DLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// MFC_DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef MFC_DLL_EXPORTS
#define MFC_DLL_API __declspec(dllexport)
#else
#define MFC_DLL_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
// This is an example of an exported variable(Can be used by MFC and Qt)
extern MFC_DLL_API int nMFC_DLL;
// This is an example of an exported function(Can be used by MFC and Qt).
MFC_DLL_API int fnMFC_DLL(void);
#ifdef __cplusplus
}
#endif
// This class is exported from the MFC_DLL.dll(Only used by MFC)
class MFC_DLL_API CMFC_DLL {
public:
CMFC_DLL(void);
// TODO: add your methods here.
public:
int add(int a, int b);
};
对应的cpp文件“MFC_DLL.cpp”代码如下:
// MFC_DLL.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "MFC_DLL.h"
// This is an example of an exported variable
MFC_DLL_API int nMFC_DLL = 32;
// This is an example of an exported function.
MFC_DLL_API int fnMFC_DLL(void)
{
return 42;
}
// This is the constructor of a class that has been exported.
// see MFC_DLL.h for the class definition
CMFC_DLL::CMFC_DLL()
{
return;
}
int CMFC_DLL::add(int a, int b)
{
return a + b;
}
void hello()
{
// ::MessageBox(NULL, "hello world!", "greeting", MB_OK);
}
int add(int a, int b)
{
return a + b;
}
2 MFC Demo
2.3 MFC中DLL使用
头文件中添加如下语句:
#include "../MFC_DLL/MFC_DLL.h"
#pragma comment(lib, "../../Bin/MFC_DLL.lib")
则可像工程本身一样使用DLL中的变量、函数和类:
void CMFC_DemoDlg::OnBnClickedButtonVariables()
{
// TODO: Add your control notification handler code here
CString str;
str.Format(_T("%d"), nMFC_DLL);
MessageBox(str, _T("Dll 中的变量"), MB_OK | MB_ICONINFORMATION);
}
void CMFC_DemoDlg::OnBnClickedButtonFunction()
{
// TODO: Add your control notification handler code here
CString str;
str.Format(_T("%d"), fnMFC_DLL());
MessageBox(str, _T("Dll 中的函数"), MB_OK | MB_ICONINFORMATION);
}
void CMFC_DemoDlg::OnBnClickedButtonClass()
{
// TODO: Add your control notification handler code here
CMFC_DLL dllClass;
CString str;
str.Format(_T("%d"), dllClass.add(5, 6));
MessageBox(str, _T("Dll 中的类"), MB_OK | MB_ICONINFORMATION);
}
特别注意:
本文只关于能够导出类的DLL使用,至于标准C DLL不属于文本讨论的范畴。
3 Qt 工程
3.1 Qt DLL创建
头文件“qt_dll.h”内容如下:
#ifndef QT_DLL_H
#define QT_DLL_H
#include "qt_dll_global.h"
extern QT_DLLSHARED_EXPORT int nQt_DLL;
QT_DLLSHARED_EXPORT int fnQt_DLL(void);
class QT_DLLSHARED_EXPORT Qt_DLL
{
public:
Qt_DLL();
public:
int add(int a, int b);
};
#endif // QT_DLL_H
对应的cpp文件“qt_dll.cpp”代码如下:
#include "qt_dll.h"
// This is an example of an exported variable
int nQt_DLL= 62;
// This is an example of an exported function.
int fnQt_DLL(void)
{
return 72;
}
Qt_DLL::Qt_DLL()
{
}
int Qt_DLL::add(int a, int b)
{
return a + b;
}
3.2 Qt Demo创建
3.3 Qt Demo中使用Qt DLL
在pro文件中添加如下代码:
LIBS += ../../Bin/Qt_DLL.dll
INCLUDEPATH += ../Qt_DLL
在要使用的dll的文件头文件中添加如下代码:
#include "qt_dll.h"
则可以按下面的示例代码一样使用Qt dll中的变量、类:
void Widget::on_btnQtVariable_clicked()
{
QMessageBox::information(this, QObject::tr("Qt DLL中的变量"), QObject::tr("%1").arg(nQt_DLL), QMessageBox::Ok);
}
void Widget::on_btnQtFunction_clicked()
{
QMessageBox::information(this, QObject::tr("Qt DLL中的函数"), QObject::tr("%1").arg(fnQt_DLL()), QMessageBox::Ok);
}
void Widget::on_btnQtClass_clicked()
{
Qt_DLL qtDll;
QMessageBox::information(this, QObject::tr("Qt DLL中的类"), QObject::tr("%1").arg(qtDll.add(7, 8)), QMessageBox::Ok);
}
3.4 Qt Demo中使用MFC DLL
同3.3节一样,在pro文件中添加如下代码:
LIBS += ../../Bin/MFC_DLL.dll
INCLUDEPATH += ../MFC_DLL
在要使用DLL的文件中包含头文件:
#include "MFC_DLL.h"
则可以按下面的示例代码一样使用Qt dll中的变量、函数,但不能使用类:
void Widget::on_btnMFCVariable_clicked()
{
QMessageBox::information(this, QObject::tr("MFC DLL中的变量"), QObject::tr("%1").arg(nMFC_DLL), QMessageBox::Ok);
}
void Widget::on_btnMFCFunction_clicked()
{
QMessageBox::information(this, QObject::tr("MFC DLL中的函数"), QObject::tr("%1").arg(fnMFC_DLL()), QMessageBox::Ok);
}
4 结论
关于结论,前面已经提过,这里再次强调一下。
1. Qt只能使用MFC导出的标准接口,无法使用MFC导出的类;
2. MFC能够使用MFC导出的类;
3. Qt能够使用Qt导出的类。
注:
关于如何使用Qt、VS进行工程搭理,如将指定DLL、exe的生成一致的路径,添加文件的相对引用等内容不属于文本讨论的范畴。
示例代码的云盘路径:
链接: http://pan.baidu.com/s/1i502Us1 密码: 37vm

本文介绍了在Qt 5.9.1和Visual Studio 2017环境下,如何创建及互相调用MFC和Qt的DLL。通过实例展示了MFC DLL的创建与使用,以及Qt DLL在Qt工程中的应用。强调了面向对象在DLL中的重要性,以及业务逻辑层代码的可移植性原则。
1万+

被折叠的 条评论
为什么被折叠?



