现在的位置: 首页 > 综合 > 正文

qt dll的调用及与主程序的交互

2018年04月30日 ⁄ 综合 ⁄ 共 1971字 ⁄ 字号 评论关闭

近期,研究了下将qt程序封装成dll,与其他程序(mfc、c#)进行调用交互,主要涉及几个方面内容:

一、qt生成dll

按照qt官方引导,可以很简单的生成dll,但是此类dll只能与qt程序进行交互;由于qt 的事件循环机制与windows寻坏机制不同,要想在其他程序中启动qt的dll,必须加入QApplication,以启动qt的事件循环机制。

通过官方发布的qtwinmigrate文件,可以非常方便的实现dll。加载exmaples/qtdll的.pro工程文件,在qtcreator可以看到main.cpp有这两个函数

BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/ )
{

    //此蔚dll的入口函数
    static bool ownApplication = FALSE;
   //启动QAppliction,具体见帮助说明

    if ( dwReason == DLL_PROCESS_ATTACH )
ownApplication = QMfcApp::pluginInstance( hInstance );
    if ( dwReason == DLL_PROCESS_DETACH && ownApplication )
delete qApp;

    return TRUE;
}

//建立导出函数

extern "C" __declspec(dllexport) bool showDialog( HWND parent )
{
    QWinWidget win( parent );
    win.showCentered();
    QMessageBox::about( &win, "About QtMfc", "QtMfc Version 1.0\nCopyright (C) 2003" );

    return TRUE;
}

qtdll工程实际引入了qtwinmigrate的三个头文件,qmafcapp、qwinhost、qwinwidget,能够连接qt程序与其他外部程序,具体功能看帮助。

在qtdll工程的基础上,将我自己的工程加入,并修改导出函数

主要是把QMessageBox换成我自己的主窗口,记得设置widget

setwindowflag(Qt::window);

setwindowModality(Qt::applicationModal);

编译后,即可生成dll。

二、调用dll

通过mfc程序调用qt 的dll,具体过程比较简单:

首先建立句柄,loadlibrary(“.dll”)

建立导出函数的指针 typedef bool(*pFun)(HWND)

将导出函数赋值给新建立的函数指针。pFun fun = (fun)GetProcAddress(hdll, "showDIalog");

调用函数即可

最后freelibrary()。

具体实现可见qtwinmigrate/exmaples/mfc/step1

问题:这样实现基本可以调用dll,但是在调用dll形成gui程序时,如果将gui程序的子窗口关闭,父窗口也自动关闭

解决方法:猜测是因为子窗口关闭时,自动退出来qt的消息循环,导致所有gui程序全部关闭,通过修改main.cpp文件的两个函数可以解决

1.注释掉if(dwReason == DLL_PROCESS_ATTACH)整句话,取消lQApplication的建立;

2.将showDialog改成int main(int argc, char* argv[])形式,并在函数中创建QApplication,形成qt的事件循环

3.在mfc主程序中,修改导出函数相应参数。

重新编译即可,实现dll的调用

三、dll调用主程序

原理与主程序调用dll基本一致,采用的是回调函数的方式(主要根据这篇文章http://lishutong.me/1075.html

在qt程序中

typedef void (*pFUn)(int* pVal);

pFun pCallBack = NULL;

建立导出函数,函数参数是pFun,并将该参数赋值给pCallBack;

qt程序在运行到符合调用条件的情况时,调用pCallBack(int*)。

在mfc程序中

typedef  void (*pFun)(int *);

typedef void (*init)fun_t)(pFUn);//参数是函数指针类型

void showFun(int *)

在程序某个函数下,

init_fun_t init = (init_fun_t)GetProcessAddress(hdll, "main")

init(showFun);

整个过程其实就是主程序通过导出函数将自己的函数指针发送给dll,dll收到指针后,在运行到符合条件的情况下,调用指针函数,将dll产生的值传送给主程序函数。

(PS:很久没写了,有点乱呵呵)

抱歉!评论已关闭.