在vs-qt环境搭好的前提下,按照下面的步骤操作即可:
1、打开vs2010,文件 --》新建 --》项目,选择Qt5 Projects --》Qt Library
2、在项目名称和位置设置好后,点击确定,然后下一步,到Project Settings界面,带界面的话勾选GUI,然后点击完成即可
3、然后会生成三个文件,这三个文件其实没有用,可以删掉。然后新建一个虚基类,这个虚基类的头文件我们是要暴露给用户的,所以尽量避免头文件的包含,另外我这里使用了结构体,所以还需要提供一个放结构体的类,然后就是新建一个继承虚基类并实现其纯虚函数方法的子类,具体代码如下:
ibaseclass.h
#ifndef IBASECLASS_H
#define IBASECLASS_H
#include "common.h"
class IBaseClass
{
public:
// 加载学生信息
virtual void LoadStudentInfo(QList<Student> &qlist) = 0;
// 获取学生信息
virtual QList<Student> GetAllStudentInfo() = 0;
};
/**
* @brief createInfoWidget接口创建了一个学生信息显示窗口的void *指针,该指针实际上是一个QWidget*的指针
*
* @param parent 父窗口,默认为空
* @return 返回学生信息显示窗口的void *类型指针
*/
extern "C" __declspec(dllexport) void * __cdecl createInfoWidget(QWidget *parent = 0);
/**
* @brief getInfoWidget接口将void *转换成IBaseClass *对象指针
*
* @param voidPlotWidget 学生信息显示窗口的void *类型指针
* @return 返回IBaseClass类型的指针,可以调用IBaseClass类的LoadStudentInfo,GetAllStudentInfo2个接口
*/
extern "C" __declspec(dllexport) IBaseClass *__cdecl getInfoWidget(void *voidInfoWidget);
/**
* @brief destroyInfoWidget接口是销毁IBaseClass *类型的学生信息显示窗口对象指针
*
* @param voidInfoWidget IBaseClass *类型的学生信息显示窗口对象指针
*/
extern "C" __declspec(dllexport) void __cdecl destroyInfoWidget(void *voidInfoWidget);
#endif // IBASECLASS_H
ibaseclass.cpp
#include <QWidget>
#include <QDebug>
#include <QMainWindow>
#include "mytest.h"
#include "ibaseclass.h"
void * __cdecl createInfoWidget(QWidget *parent)
{
QWidget* pwidget = new MyTest(parent); //MyTest继承QWidget,所以也属于QWidget
if (parent != NULL)
{
QMainWindow* pMainWindow = dynamic_cast<QMainWindow*>(parent); //这里指定父窗口使用QMainWindow,所以加以判断
Q_ASSERT(pMainWindow); //对pMainWindow断言,判断parent是否属于QMainWindow及其子类
if (pMainWindow == NULL)
{
return NULL;
}
pMainWindow->setCentralWidget(pwidget);
}
return (void *)pwidget; //最后返回一个void *指针
}
IBaseClass *__cdecl getInfoWidget(void *voidInfoWidget)
{
//通过createInfoWidget返回的void *指针转换成为QWidget *,
//看似这一步有点多余,但这是比较稳的操作
//这里注意:指针转换之前怎么转换来的,需要一步步再转换回去,例如
//要从void *-->QWidget *-->MyTest *-->IBaseClass*
//不能直接从void *-->IBaseClass*,这样会出错
QWidget* pwidget = (QWidget*)voidInfoWidget;
MyTest*pInfoWidget = dynamic_cast<MyTest*>(pwidget);
Q_ASSERT(pInfoWidget); //对pInfoWidget断言,判断pInfoWidget是否属于MyTest及其子类
if(pInfoWidget == NULL)
{
return NULL;
}
IBaseClass* pIBaseClass = dynamic_cast<IBaseClass*>(pInfoWidget); //将MyTest*转换成IBaseClass*,供外部调用
return pIBaseClass;
}
void __cdecl destroyInfoWidget(void *voidInfoWidget)
{
if (voidInfoWidget != NULL)
{
delete voidInfoWidget;
}
voidInfoWidget = NULL;
}
common.h
#ifndef COMMON_H
#define COMMON_H
#include <QMetaType>
#include <QString>
struct Student
{
QString strClass;
QString strName;
QString strSex;
QString strNo;
};
Q_DECLARE_METATYPE(Student);
#endif //COMMON_H
mytest.h
#ifndef MYTEST_H
#define MYTEST_H
#include <QtWidgets/QWidget>
#include "ui_mytest.h"
#include "common.h"
#include "ibaseclass.h"
class MyTest : public QWidget, public IBaseClass
{
Q_OBJECT
public:
MyTest(QWidget *parent = 0);
~MyTest();
protected://IBaseClass
virtual void LoadStudentInfo(QList<Student> &qlist);
virtual QList<Student> GetAllStudentInfo();
private:
Ui::MyTestClass ui;
};
#endif // MYTEST_H
mytest.cpp
#include "mytest.h"
MyTest::MyTest(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
MyTest::~MyTest()
{
}
void MyTest::LoadStudentInfo(QList<Student> &qlist)
{
foreach(const Student &s, qlist)
{
ui.class_lineEdit->setText(s.strClass);
ui.name_lineEdit->setText(s.strName);
ui.sex_lineEdit->setText(s.strSex);
ui.no_lineEdit->setText(s.strNo);
}
}
QList<Student> MyTest::GetAllStudentInfo()
{
QList<Student> qlist;
Student s;
s.strClass = ui.class_lineEdit->text();
s.strName = ui.name_lineEdit->text();
s.strSex = ui.sex_lineEdit->text();
s.strNo = ui.no_lineEdit->text();
qlist.push_back(s);
return qlist;
}
mytest.ui
由于xml太长也很简单就只截个图了
选中项目名称,右键–》生成,生成成功后会在win32/Debug目录下生成dll,然后提供ibaseclass.h,common.h,和MyDll.dll这三个文件就可以动态加载使用了,见下一篇博客