最近在修改Meshlab的源代码,使其能够展示我们自己的数据格式。看Meshlab源代码的时候发现它的架构非常漂亮,因此决定好好研究一下,后面其他代码重构的时候可以参考这个架构。
Meshlab使用Qt实现,整体工程由主窗体和多个子功能模块组成,使用Subdirs工程文件进行子项目的组织。各个子模块与主窗体是松耦合的,编译时不相互依赖,编译完成之后主窗体加载模块的动态链接库,如果没有相应的库或者加载失败则没有相应功能,而不影响其他功能。
我编译时使用如下的一个Subdirs工程文件
TEMPLATE= subdirs
CONFIG+= ordered
SUBDIRS= common \
meshlab \
meshlabplugins/io_rawdata
一共编译三个子工程,common,meshlab
以及io_rawdata
,前两个工程是Meshlab的基础,是必需编译的,最后一个是可选的功能模块。下面分别介绍一下这三个子工程。
common
工程编译出来是一个静态库,其他所有的工程都需要链接这个静态库common.lib
,这个工程只是负责接口的声明,功能由具体的模块实现,由主窗体调用。比如我编写如下的一个接口声明一个纯虚函数testFunc
,这个函数会由io_rawdata
实现,并在meshlab
中被调用。
class RawDataIOInterface
{
public:
RawDataIOInterface(){}
virtual int testFunc()=0;
};
#define RawDataIOInterface_IID "com.dinglufe.RawDataIOInterface"
Q_DECLARE_INTERFACE(RawDataIOInterface,RawDataIOInterface_IID)
meshlab
工程是主窗体部分,也是整个工程的核心,负责界面和交互,其他的一些工程通过加载动态链接库使用。比如可以加载io_rawdata.dll
使用RawDataIOInterface
中声明的testFunc
,测试代码如下
#include <common/rawdataiointerface.h>
#include <QPluginLoader>
#include <QDebug>
void testRawDataFunc()
{
QPluginLoader loader("plugins/io_rawdata.dll");
QObject *plugin = loader.instance();
RawDataIOInterface *iRawDataIO = qobject_cast<RawDataIOInterface *>(plugin);
qDebug()<<iRawDataIO->testFunc();
}
最后是io_rawdata
工程,这是一个工程模块,这个模块负责io
相关的一些功能,比如读取我们自己的文件格式,同样依赖于common
工程获取相应的接口,然后实现其中声明的功能,比如如下一段测试代码
#include <common/rawdataiointerface.h>
class RawDataIO : public RawDataIOInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID RawDataIOInterface_IID)
Q_INTERFACES(RawDataIOInterface)
public:
RawDataIO():RawDataIOInterface(){}
int testFunc(){return 1;}
};
实现了RawDataIOInterface
所声明的testFunc
函数。
当然了,以上说的这些东西都只不过是QPlugin
的使用简介而已。关于代码的组织,meshlab还有很多不错的设计,可以去阅读一下它的代码。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。