1、
问题:
可以确定环境没有任何问题,但是一运行就这样。
解决:
删掉这个文件夹
2、
在编写插件添加资源文件的过程中,有些教程说前缀需要和工程名一致。经过测试,不是和工程名一致,而是与生成的dll名字一致,也就是TARGET
其他地方,如工程名、 MANIFEST.MF里的符号,都是随便取。
3、
刚开始我有个想法,为什么必须要有接口,感觉多此一举,需要的功能在实现类就能完全体现了。可不可以只有实现类+激活类,如下工程:
结果是不行的,原理还不知道,反正使用这个dll就会报错:
总结上面:
①、如果一个类不继承一个接口类,那么这个类是不能使用registerService注册到ctk框架的,如果强行注册,在安装和启动此插件的时候就会报错;
②、但是完全可以使用一个没有继承接口类的类,如何使用呢?首先定义类的功能函数,如定时向ctk发送事务,然后通过在Activator的start开启这个类的定时器,这样虽然能够正常使用,但是却无法通过ctk获取到这个插件,毕竟它不是服务【无法注册成服务】,它的作用在Activator的start里就已经用掉了。
③、如果实在不想写接口类,可以继承ctk提供的ctkEventHandler类,这个类主要用于提供插件间通信【event方式】,然后把其他函数定义成当前类自己的函数就行了。
4、
生成的插件名不要有下划线,因为CTK会默认将插件名中的下划线替换成点号,最后后就导致找不到插件
5、
在获取服务的时候,有两个重载方式【可直接使用的】
1、AbsLogService* ret = context->getService<AbsLogService>(reference); 2、AbsLogService* ret = qobject_cast<AbsLogService*>(context->getService(reference));
其中第一个方式的原型是
第二个方式的原型是
第一个方式实际在内部调用的第二个方式,然后实现一个qobject_cast强制转换再返回;而第二个方式是直接返回QObject指针。
问题来了:获取的服务必须要完成qobject_cast转换。
我试过如下代码
QObject* ret = context->getService(reference);
就是使用第二个方式,不进行操作,然后代码就在这里卡住了,具体原因不是很清楚,应该涉及到跨动态库数据转换之类的知识。。。
6、
如果想把ctk初始化、插件安装启动、获取等操作封装成一个类,那么要注意:需要把ctk相关的变量定义成类属性,不能是局部变量,否则会出现各种问题如获取不了服务、服务引用为空等。
ctkPluginFrameworkFactory frameworkFactory;
ctkPluginContext* context = nullptr;
7、
在使用1接口2插件的时候,虽然是两个插件,也会有两个激活类【从原理上来讲1个激活类就行了,但是在start里注册两次】,其中的IID只能有一个,
如果有两个会出现报错:
应该是从Qt插件基础上来说,一个dll只能有一个IID
8、
有时候出现一个现象,两个完全相同调用CTK框架的工程,第一个能正常访问CTK,第二个却不能,直接运行就退出了。
可能原因是:两个工程访问的是同一个CTK动态库,第一个访问之后,虽然程序关了,但是没有正确关闭CTK,所以导致后台还认为当前程序占用着此CTK动态库,其他工程就自然访问失败了。
解决:重启Qt
9、
使用CTK的时候,尽量不要使用中文【qDebug】,不然可能会打印乱码;有时候加中文可能都直接编译不过。。。
10、
经过实测:
VS2015编译出的CTK,使用QT+MSVC2015_64失败;Qt+MSVC2017_64可行
VS2017编译出的CTK,可正常使用,在Qt+MSVC2015_64、Qt+MSVC2017_64都测试过,但是无法在Qt+MingW里使用;
MingW编译出的CTK,任何环境都无法使用
11、
经过实测:同一路径的插件是可以多次安装、启动,并且不会报错,并且它们的id是一致的【相当于如果安装已经安装了某路径的插件,会直接返回】;但是将这个插件放在不同路径是会安装失败的
注意,这里的同一插件是指插件名称,而不是MF里的name
12、
可直接在MF文件里添加自己特有的元数据,如:
13、关于升级插件时遇到的问题
即使是被停止、卸载的插件,还是被框架占用,无法对其删除,可以复制;
某个插件刚开始安装的时候是V1.0,卸载之后第二次安装的时候是V2.0,此时插件提供的接口都更新成功,但是通过读取MF文件的headers还是V1.0的信息;
同一路径的某插件,安装多次,虽然不会报错,但是除了第一次,后面全部都直接返回,不会对框架产生任何变化,把第一次安装成为有效安装。【如安装A-安装A-安装A,只有第一次安装才是有效的,后面没有任何作用】;
同一插件【接口名称相同,实现可以不同,版本也可以不同】放在不同路径,如果都安装了,那么调用的接口是最后那次”有效”’安装的插件的。【如安装A-安装B,那么最后调用的B;安装A-安装B-安装A,最后调用的是B,因为最后一次安装A是无效安装】;
如果生成了a.dll插件,我们手动把命名改成了a.1.0.0.dll,此时是无法安装成功的;