最近因为工作上的需要,对系统在架构上进行解耦,参考之前做的东西考虑对进程间通信封装一个动态库,不同的进程加载动态库提供的通用接口来进行消息收发。正好在学习qt,于是基于qt的qlocalserver来进行了动态库的开发。开发完成之后,问题来了。。。有一部分功能是使用网页来展现的,我们用了一个公司买的封装过的浏览器来加载网页,网页的事件由浏览器加载的np插件来响应,我的思路就是我用开发的np插件(这也是一个动态库)加载我的动态库,来实现np插件与我的服务进程之间的通信。开发都很顺利。。。编译,使用dependence查看动态库是否有依赖缺失,显示也很正常,但是浏览器加载np插件的时候就插件就崩溃了,报出这样的错误:Cannot create a win event notifier without a QEventDispatcherWin32。
百度之,答案是这样的:https://stackoverflow.com/questions/3511044/cannot-create-a-win-event-notifier-without-a-qeventdispatcherwin32。
这人说他是用release版本的应用调用了debug版本的动态库。因为我的都是用的debug版本的,所以显然不是这个错误了。
继续百度,相关的几乎没有,回到调试的工程,发现是在初始化一个qlocalsocket对象的时候崩溃的,往下调试的话会发现在报错是出现在这个文件qwineventnotifier_p.cpp的这句话
QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher);
这个d->threadData->eventDispatcher在内存中调看是空的。哎。对qt我也是初学者,老老实实地再去google一下吧。(真的感觉百度不好用,特别是这种偏门的错误,百度几乎没有。之前做过一个qt的文件树也是百度啥也搜不到,这个准备另写一篇)也搜了bing,结果前三条都是跟上面一样的,但是还是有一条引起了我的注意:
http://www.qtcentre.org/archive/index.php/t-43522.html
这里面作者列举了一个在启动QCoreApplication a(argc,argv)之前访问QObject引起错误的实例。当然后面乱七八糟的回复也没人说解决了这个问题。但是这给了我一个思路,因为np插件是c++写的,加载np插件的plugins-container.exe显然也不是qt写的,而我之前调试的时候都是使用qt进程进行的。因此我立即写了一个简单的c++win32控制台程序来加载我的插件,果然出现了上面的错误。
问题找到了,显然qt的一些类(基于QObject)是需要基于一个QCoreApplication的实例化对象的,这样再去搜索找到这样一个答案:https://stackoverflow.com/questions/2150488/using-a-qt-based-dll-in-a-non-qt-application。
参照答主自己的描述(他自己提供了一个解决方法),因为我们整个动态库的主线程使用了qlocalserver,所以我在插件的入口加上这样的代码:
QCoreApplication *_pQCoreApplication; if (QCoreApplication::instance() == NULL) {
//如果不是qt进程 则自己实例化一个QCoreApplication int argc = 1; char* argv[] = { "dummy.exe", NULL };//进程名可以随便起一个 无所谓的 _pQCoreApplication = new QCoreApplication(argc, argv); _pQCoreApplication.processEvents(); } else { _pQCoreApplication = NULL; }
问题是解决了,进程运行也正常了,无论是内存还是析构都没有报出异常,但是问题和提问者是一样的,就是这样使用是否安全,以及是否合适,还有待思考和查询。
待续。