我做得对吗?
我的一个客户有一个小组,我正在开发基于Qt的客户端 - 服务器的东西,有很多有趣的小部件和套接字.
公司内的另一个团队希望使用基于QTcpSocket的客户端数据提供程序类的封装版本.(基本上它听起来像,提供从服务器到客户端显示器的数据)
但是,该组有一个巨大的应用程序,主要是使用MFC构建的,这根本不会很快改变.基于Qt的DLL也是延迟加载的,因此在某些配置中可以在没有此功能的情况下部署它.
我有它的工作,但它有点hacky.这是我目前的解决方案:
DLL包装器类构造函数调用QCoreApplication :: instance()以查看它是否为NULL.如果它为NULL,则假定它在非Qt应用程序中,并创建它自己的QCoreApplication实例:
if (QCoreApplication::instance() == NULL)
{
int argc = 1;
char* argv[] = { "dummy.exe", NULL };
d->_app = new QCoreApplication(argc, argv); // safe?
}
else
d->_app = NULL;
Run Code Online (Sandbox Code Playgroud)
然后它将设置一个Windows计时器,偶尔调用processEvents():
if (eventTimerInterval > 0)
{
// STATE: start a timer to occasionally process the Qt events in the event queue
SetTimer(NULL, (UINT_PTR)this, eventTimerInterval, CDatabaseLayer_TimerCallback);
}
Run Code Online (Sandbox Code Playgroud)
回调只是使用timerID作为指向类实例的指针来调用processEvents()函数.SetTimer()文档说当HWND为NULL时它会忽略timerID,所以这看起来完全有效.
VOID CALLBACK BLAHBLAH_TimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
((BLAHBLAH*)idEvent)->processEvents(); // basically just calls d->_app->processEvents();
}
Run Code Online (Sandbox Code Playgroud)
然后我将QCoreApplication实例销毁为析构函数中的最后一个东西.
BLAHBLAH::~BLAHBLAH()
{
.. other stuff
QCoreApplication* app = d->_app;
d->_app = NULL;
delete d;
if (app != NULL)
delete app;
}
Run Code Online (Sandbox Code Playgroud)
如果托管应用程序希望对processEvents()本身的调用计时,它可以为eventTimerInterval传递0并调用BLAHBLAH :: processEvents()本身.
有什么想法吗?将该应用程序移植到Qt不是一种选择.这不是我们的.
它似乎有效,但这里可能有几个假设被打破.我可以用这样的伪参数构建一个QCoreApplication吗?事件队列是否可以安全地以这种方式运行?
我不希望以后在我面前爆炸.思考?
研究Qt代码似乎需要QCoreApplication来调度系统范围的消息,例如定时器事件.信号/插槽甚至QThreads之类的东西都不依赖于它,除非它们与那些系统范围的消息有关.以下是我在共享库中的方式(使用Qt本身的跨平台方式),我实际上是调用exec,因为processEvents()本身并不处理所有内容.
我有一个全局命名空间:
// Private Qt application
namespace QAppPriv
{
static int argc = 1;
static char * argv[] = {"sharedlib.app", NULL};
static QCoreApplication * pApp = NULL;
static QThread * pThread = NULL;
};
Run Code Online (Sandbox Code Playgroud)
我在QObject(即moc'ed)中有一个OpenApp方法,如下所示:
// Initialize the app
if (QAppPriv::pThread == NULL)
{
// Separate thread for application thread
QAppPriv::pThread = new QThread();
// Direct connection is mandatory
connect(QAppPriv::pThread, SIGNAL(started()), this, SLOT(OnExec()), Qt::DirectConnection);
QAppPriv::pThread->start();
}
Run Code Online (Sandbox Code Playgroud)
这是OnExec插槽:
if (QCoreApplication::instance() == NULL)
{
QAppPriv::pApp = new QCoreApplication(QAppPriv::argc, QAppPriv::argv);
QAppPriv::pApp->exec();
if (QAppPriv::pApp)
delete QAppPriv::pApp;
}
Run Code Online (Sandbox Code Playgroud)
到目前为止似乎工作正常,我不确定我是否需要在最后删除应用程序,如果我找到了什么,我会更新我的答案.
4.5.2 的 Qt 文档表示 QCoreApplication 的参数需要具有与应用程序对象一样长的生命周期 - 因此您不应该真正使用局部变量。
除了那件小事:
我正在努力解决同样的问题,一切似乎也对我有用。但是,我建议在卸载/退出时非常小心,因为如果您正在使用另一个应用程序的事件循环,并且该事件循环在您的库卸载之前停止,那么当您尝试关闭时,可能会发生各种崩溃的情况。 () 套接字并删除 QObject。
| 归档时间: |
|
| 查看次数: |
11986 次 |
| 最近记录: |