基于Python插件的C++扩展框架

时光总嘲笑我的痴心妄想 提交于 2019-11-30 05:22:51

这里介绍一种典型的C++应用框架,使用Python进行扩展。比如GIMP/Blender/QGIS等等Linux上面的开源软件,还有很多商业软件也采用了这一技术路线。但是由于Python的灵活性,可以使用C/C++直接扩展,或者基于SWIG、PyQt、PythonQt进行扩展,导致具体实现上存在较大的差异。大部分的关于Python插件介绍都是关于Python本身的,因为Pytho是个动态语言,实现这一点并不难(参考:http://my.oschina.net/u/2306127/blog/489795),但在很多应用中,对性能要求较高,一般需要用C/C++来实现。然后,把Python解释引擎嵌入进去,方便用户进行参数定制、功能扩展和模块组装。

这里介绍一个笔者摸索的使用Qt+SIP+PyQt+Python的技术路线,是功能比较强大、技术成熟、封装工作量相对较小的一种,而且具有商业级的发展潜力。

一、插件体系的组成

1.1 主程序对象的Python封装

一般情况下,我们把主程序的C++类通过SIP进行封装,然后就可以在Python Shell中通过Python直接调用了。

1.2 集成脚本控制台和编辑窗口

然后再把Python的控制台集成到主程序窗口中,就可以直接通过Python控制主窗口的操作。这里需要干两件事情,一是把控制台窗口嵌入主窗口中,二是要把主程序的对象句柄传给Python解释器环境。如果由Python自行初始化,主窗口的对象和解释器的对象就不是同一个,无法相互操作。当然,也可以通过全局静态对象等方式共享主程序,但不建议这样做,会影响后续程序的可扩展性。当获得主程序的对象句柄后,所有基于该对象的脚本操作,就会在主程序中得到反映。当然,如果涉及到了线程操作,这个问题会变的相当复杂,这里不予讨论,假设都是在主线程中进行的操作。

1.3 插件管理器和插件运行组件

既然是插件结构,当然就不会只有几个插件了,而是允许大量的插件可以动态加载进来,因此就需要一个插件管理器。插件管理器首先完成插件的管理,包括安装、启用、卸载、显示信息等等,一般提供一个对话框来完成。插件管理组件还需要负责在系统启动时进行插件的加载,给插件提供查询接口以实现插件的相互调用,以及执行插件的运行和错误跟踪、日志记录等等。

二、插件的基本接口

插件一般包含load、unload、run、info、about等基本接口。

在load时要把运行的主程序环境句柄传送给插件,而插件应该将此缓存起来,后续就可以直接使用了,如果属于UI插件,此时执行添加菜单项、工具栏、注册事件响应的回调函数等操作。

run()用于执行真正的功能操作。

info()一般返回一个插件的元数据描述对象,而about()一般弹出一个插件自己的信息说明对话框。

在最后需要将插件卸载时,宿主程序调用unload()。

如果需要更复杂的控制,可以加入init()等函数。

原则上,插件接口应该是一个最小集合,这样便于使用和插件的开发。更多的功能应该放在插件加载完成后再行操作。

三、Qt+SIP+PyQt+Python插件系统

为什么采用Qt+SIP+PyQt+Python这一套技术路线呢?

1、首先,要做一个基于C++的应用一般会有一个UI界面,用QT来做,简单美观跨平台。

2、Qt已经有成熟的PyQt的Python封装,可以直接引入基于python的界面访问库。如果用别的界面库,需要自己对界面库全部用Python封装一遍,这个工作量就相当大了,而且还有很大的技术难度,维护升级的成本也是相当高的。

3、SIP可以把自己的各种C++库快速封装为Python库,易于维护和更新、升级。自己的库和Qt的库就可以在Python中同时使用了。

4、主程序使用Qt来开发,通过统一的SIP方式进行对象的封装,并把接口传送到Python解释器的执行环境,这样Python的插件就可以访问到宿主程序的所有对象资源了。

5、为什么没有使用SWIG呢?同样的原因,因为Qt的界面库和PyQt的Python封装库已经成熟而且广泛使用了。

目前还缺少的是一个插件的标准接口和插件管理器、插件运行的stub。

通过Qt开发一个插件管理器PluginsManager,执行启动时插件的扫描加载、宿主程序事件的分派管理、基于插件名称的功能调用、插件安装卸载启用禁用管理对话框等。PluginsManager在装入插件时,将把主程序句柄传送给插件,而插件将把该句柄连接到主程序的Python封装对象里,实现插件与宿主程序的内存对象的对接。

Qt+SIP+PyQt+Python技术路线,既能得益于Qt/PyQT的已有成果的强大功能和标准化的接口,技术难度和成本都是比较低的,而且所封装的库既能在C++的图形界面下运行,也可以独立出来通过python的shell直接执行,而不需要进行两次封装。

具体的实现,目前还没有发现现成的框架,等有时间了准备自己搞一个,大家有兴趣的也可以试一试,然后开源出来,共同完善。

需要注意一点:Qt/Sip/PyQt都提供了开源的免费GPL版本,也要求所做的后续衍生工作也要开源。如果用于商业应用,可以购买相应的商业许可,然后用商业版重新编译一次即可。




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!