在非Qt应用程序中使用基于Qt的DLL [英] Using a Qt-based DLL in a non-Qt application

查看:147
本文介绍了在非Qt应用程序中使用基于Qt的DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的客户有一组我正在开发基于Qt的客户端服务器的东西,有很多有趣的小部件的东西和套接字。



公司内的另一个组织希望使用基于QTcpSocket的客户端数据提供者类的封装版本。 (这基本上是什么样的,从服务器提供数据到客户端显示)



然而,该组有一个巨大的应用程序主要使用MFC,这是根本不会随便改变。基于Qt的DLL也是延迟加载,以便在某些配置中可以部署该功能。



我已经工作了,但这有点黑客。这是我现在的解决方案:



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); //安全吗
}
else
d-> _app = NULL;

然后将设置一个Windows计时器偶尔调用processEvents():

  if(eventTimerInterval> 0)
{
// STATE:启动定时器来偶尔处理事件中的Qt事件队列
SetTimer(NULL,(UINT_PTR)this,eventTimerInterval,CDatabaseLayer_TimerCallback);
}

回调简单地使用timerID作为指针来调用processEvents()函数类实例。 SetTimer()文档说HWND为NULL时,它会忽略timerID,因此看起来完全有效。

  VOID CALLBACK BLAHBLAH_TimerCallback (HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
((BLAHBLAH *)idEvent) - > processEvents(); //基本上只是调用d-> _app-> processEvents();
}

然后我将毁灭QCoreApplication实例作为析构函数中的最后一件事。 / p>

  BLAHBLAH ::〜BLAHBLAH()
{
..其他东西

QCoreApplication * app = d-> _app;
d-> _app = NULL;
删除d;
if(app!= NULL)
删除应用程序;
}

如果托管应用程序希望对processEvents()本身进行调用,它可以为eventTimerInterval传递0,并调用BLAHBLAH :: processEvents()本身。



有什么想法?将该应用移植到Qt是不可选的。这不是我们的。



似乎有效,但在这里可能有几个假设被破坏。我可以用这样的虚拟参数构造QCoreApplication吗?事件队列是否安全地以这种方式运作?



我不想让我以后再次吹起来。思想?

解决方案

学习Qt代码似乎需要QCoreApplication来调度系统范围的消息,如定时器事件。像信号/插槽甚至QThreads这样的事情不依赖于它,除非它们与这些系统范围的消息相关。这是我在一个共享库(以跨平台的方式使用Qt本身)这样做的,我实际上调用 exec ,因为只有processEvents()不处理一切



我有一个全局命名空间:

  //私有Qt应用程序
命名空间QAppPriv
{
static int argc = 1;
static char * argv [] = {sharedlib.app,NULL};
static QCoreApplication * pApp = NULL;
static QThread * pThread = NULL;
};

我在QObject OpenApp 方法>(这是moc'ed)这样:

  //初始化应用程序
if(QAppPriv :: pThread == NULL)
{
//应用程序线程的单独线程
QAppPriv :: pThread = new QThread();
//直接连接是必需的
connect(QAppPriv :: pThread,SIGNAL(started()),这个,SLOT(OnExec()),Qt :: DirectConnection);
QAppPriv :: pThread-> start();
}

这里是OnExec 插槽:

  if(QCoreApplication :: instance()== NULL)
{
QAppPriv :: pApp = new QCoreApplication QAppPriv :: argc,QAppPriv :: argv);
QAppPriv :: pApp-> exec();
if(QAppPriv :: pApp)
删除QAppPriv :: pApp;
}

到目前为止,它似乎工作正常,我不知道是否需要要删除最后的应用程序,如果我找到某些东西,我会更新我的答案。


Am I doing it right?

A client of mine has a group where I'm developing Qt-based client-server stuff with a lot of fun widget stuff and sockets.

Another group within the company wants to use a wrapped version of the QTcpSocket-based client data provider classes. (Which does basically what it sounds like, provides data from the server to the client displays)

However, that group has a huge application built mostly with MFC, and that is simply not going to change any time soon. The Qt-based DLL is also delay-loading so that it can be deployed without this feature in certain configurations.

I've got it working, but it's a little hacky. Here's my solution at the moment:

The DLL wrapper class constructor calls QCoreApplication::instance() to see if it's NULL or not. If it's NULL, it assumes it's in a non-Qt app, and creates a QCoreApplication instance of it's own:

if (QCoreApplication::instance() == NULL)
{
    int argc = 1;
    char* argv[] = { "dummy.exe", NULL };
    d->_app = new QCoreApplication(argc, argv);  // safe?
}
else
    d->_app = NULL;

It then will set up a windows timer to occasionally call 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);
}

The callback simply calls the processEvents() function using the timerID as a pointer to the class instance. The SetTimer() docs say when HWND is NULL it ignores the timerID, so this appears to be perfectly valid.

VOID CALLBACK BLAHBLAH_TimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    ((BLAHBLAH*)idEvent)->processEvents(); // basically just calls d->_app->processEvents();
}

I then destroy the QCoreApplication instance as the very last thing in the destructor.

BLAHBLAH::~BLAHBLAH()
{
    .. other stuff

   QCoreApplication* app = d->_app;
   d->_app = NULL;
   delete d;
   if (app != NULL)
       delete app;
}

If the hosting application wishes to time the calls to processEvents() itself, it can pass 0 in for eventTimerInterval and call BLAHBLAH::processEvents() itself.

Any thoughts on this? Porting that app to Qt is not an option. It's not ours.

It appears to work, but there are probably several assumptions being broken here. Can I just construct a QCoreApplication with dummy arguments like that? Is the event queue safe to operate in this manner?

I don't want this blowing up in my face later. Thoughts?

解决方案

Studying the Qt code it seems QCoreApplication is needed to dispatch system-wide messages such as timer events. Things like signal/slots and even QThreads do not depend on it unless they are related to those system-wide messages. Here is how I do this in a shared library (in a cross platform way using Qt itself) and I actually do call exec, because processEvents() alone does not process everything.

I have a global namespace:

// Private Qt application
namespace QAppPriv
{
    static int argc = 1;
    static char * argv[] = {"sharedlib.app", NULL};
    static QCoreApplication * pApp = NULL;
    static QThread * pThread = NULL;
};

I have an OpenApp method in a QObject (that is moc'ed) like this:

// 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();
}

And here is OnExec slot:

if (QCoreApplication::instance() == NULL)
{
    QAppPriv::pApp = new QCoreApplication(QAppPriv::argc, QAppPriv::argv);
    QAppPriv::pApp->exec();
    if (QAppPriv::pApp)
        delete QAppPriv::pApp;
}

So far it seems to be working fine, I am not sure if I need to delete the app at the end, I will update my answer if I find something.

这篇关于在非Qt应用程序中使用基于Qt的DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆