缘起
Qt插件不仅可以通过动态地导入功能代码,而且也可以动态地导入与插件相对应的界面元素。说白了就是界面中的控件会根据你导入了什么控件而动态地增删相对应的widgets.
Qt例程的做法
在Qt的Plug&Paint例程中,是通过导入插件之后,再根据不同的Interface建立相应的连接。 自己遇到的问题当用QPluginLoader中的instance导入动态链接库的时候,如果你是在初始化的时候emit (signals), 那么实际上,这个信号已经发出去了,等你再用connect连接的时候,实际上已经不起作用了。
如何解决这个问题?
可能方法一:有没有可能预先判断其类型,然后先建立连接,等导入的时候同样在插件内部初始化的时候即释放消息,从而建立连接?或者 可能方法二: 利用一个外部的接口或类来管理插件的导入,等加载完后再emit其消息?
在发现了问题之后,我尝试使用第二种方法,可以解决问题,这就是说等所有连接都建立之后,主要程序才发送signal,这样之前控件的连接则可以建立。
另外,再次翻看OpenFlipper的源码,发现其是如下做到的:在OpenFlipper中,是通过定义一个BaseInterface来做的,其中包含了pluginsInitialized()及initializePlugin()这两个函数。这两个函数的作用是不相同的,initializPlugin在所有插件的Interface导入之后,利用plugin的元信息(metaObejct)来invoke这个特定的method.具体的使用可参见以下这个函数:
Bool QMetaObject::invokeMethod(…)
而每个QObject都会有相应的QMetaObject.通过QPluginLoader导入的plugin实际上也是一个QObject.在OpenFlipper中,通过MetaObject在插件导入后就调用initializePlugin,主要负责建立该插件相关的一些内部数据以及emit一些signals,因为signals这些数据不能在初始化的时候用,而只能在连接建立后才可以emit出来。
而实际上,其所有的插件都需要继承自BaseInterface,而在BaseInterface的定义中,也明确了两个slots:一个是 Virtual void initializePlugin() //此处是用于建立内部的connection,外部的connection是不允许的(因为其会被忽略)。那既然initializePlugin已经将所有内部消息及连接已经建立了,为什么还要pluginsInitialize()这个signal呢,这主要是因为OpenFlipper加入了脚本的支持,大部分的脚本驱动的调用代码都是通过virtual void pluginsInitialized()函数来初始化。 从中可以看出,OpenFlipper实际上使用的第二种思路,其相应的代码在OpenFlipper/OpenFlipper/Core/PluginLoader.cc中。
摘自:http://blog.csdn.net/jingwenlai_scut/article/details/5653743