Skip to content
rhcad edited this page Feb 17, 2012 · 14 revisions

插件原理

本框架中所提到的C++插件,即可以是动态链接库文件(DLL/SO),也可以是可执行程序文件;通过在插件文件中实现统一的导出函数,使得其他模块可以自动通过这些导出函数访问其接口。

一、插件工作原理

插件原理图

插件系统主要有两种使用形式,一是在C++的主程序或动态库中使用C++插件,另一种是在Python等其他编程语言中使用C++插件。

1、插件管理器(x3manager)

插件管理器(x3manager)也是一个插件,按照统一标准实现了插件的导出函数。x3manager插件的主要作用是在多个插件之间进行中介联系,从而允许插件之间能够互相访问而不直接发生联系,各个插件动态库加载后自动向x3manager登记。例如要创建一个对象,通过插件管理器来查询是在哪个插件中实现了该类,从而创建出对象、访问接口功能。

相对于之前的 x3c插件框架,x3py插件框架中的插件管理器不负责插件动态库的加载管理,只保留中介作用,由应用程序等外部模块来加载插件动态库文件。由于提供了多种加载方法,这样更灵活、职责更清晰。

2、C++程序使用C++插件

在C++的主程序或动态库中使用C++插件时,先加载各个插件动态库,然后就可使用插件接口。插件加载方式的详细说明见 如何加载插件

3、Python等语言使用C++插件

Python、Perl、Ruby、Java、C#、PHP 等编程语言如果需要使用C++插件,可以通过使用SWIG以代理的方式实现;原理为:使用SWIG生成面向特定编程语言的封装代码,在该封装代码中调用C++插件,然后编译该封装代码就得到能让对应编程语言可调用的扩展模块。

二、插件调用过程

在插件实现时,通过包含 pluginimpl.h 文件,自动实现了 x3InternalCreate、x3InitPlugin、x3FreePlugin、x3CreateObject 这四个导出函数,通过导出函数就可在插件之间建立联系。下面将说明这四个导出函数之间的联系。

1、加载插件

加载插件的序列图

使用 x3LoadLibrary 函数加载动态库文件。使用此函数而不是WinAPI的 LoadLibraryA 函数,是为了确保在VC++、MinGW GCC、Linux、Mac 等编译环境下能正常加载动态库文件,且确保自动调用 x3InitPlugin 函数进行插件初始化。

x3InitPlugin 函数用于在插件加载时进行初始化、向管理器登记(x3RegisterPlugin)此插件的所有类ID(CLSID串)。通过在插件CPP文件中包含 pluginimpl.h 文件,自动实现了 x3InitPlugin。插件动态库被多次加载时不会多次重复初始化,这是在 x3InitPlugin 函数中通过计数来保证的。

x3Initialize 函数由各个插件自行实现,用来完成附加的初始化操作,由 x3InitPlugin 函数调用。

插件加载方式的详细说明见 如何加载插件

2、卸载插件

卸载插件的序列图

使用 x3FreeLibrary 函数卸载动态库文件。使用此函数而不是WinAPI的 FreeLibrary 函数,是为了确保在VC++、MinGW GCC、Linux、Mac 等编译环境下能正常卸载动态库文件,且确保自动调用 x3FreePlugin 函数进行插件注销。

x3FreePlugin 函数用于在插件卸载时进行对象释放、向管理器注销(x3UnregisterPlugin)此插件的信息。通过在插件CPP文件中包含 pluginimpl.h 文件,自动实现了 x3FreePlugin。

x3Uninitialize 函数由各个插件自行实现,用来完成附加的资源释放操作,由 x3FreePlugin 函数调用。

3、使用插件接口

使用插件接口的序列图

通过使用智能指针模板类 x3::Object 来使用插件接口,自动处理引用计数。

x3::Object模板类通过x3::createObject函数去调用 x3CreateObject 导出函数来创建对象。如果插件自身的 x3InternalCreate 不能创建对象,则再转给插件管理器,由后者根据类ID查找对应插件,然后调用对应插件的 x3InternalCreate 函数。

插件接口的更多使用说明见 如何使用插件接口