【问题标题】:Qt - Dialog in a DLLQt - DLL 中的对话框
【发布时间】:2015-06-18 06:33:46
【问题描述】:

在我的公司,我们正在使用 Embarcadero-C++-IDE 进行开发(这很不舒服)。为了开始离开,我们将 dll 中的单个对话框移植到 Qt。例如,我的 qt-dll-code 看起来像这样

extern "C" ROBOTECHPOLYLINEDIALOGSHARED_EXPORT void popupRoboTechDialog()
{
    if( ! QApplication::instance() )
    {
    int argc = 1;
    char *argv[] = {"Design polyline"};
    QApplication app(argc, argv);
    RoboTechPolyline dialog;
    dialog.show();
    app.exec();
    }
    else
    {
    RoboTechPolyline Dialog;
    Dialog.exec(); 
    }  
}

尝试从像这里 Starting Qt GUI from dll (in DLLStart function) 这样的另一个线程启动对话框确实使我的对话框没有响应,但我认为这个问题和我的问题没有太大关系。

我正在从主应用程序动态加载这个 Dll,它工作正常。但是,当我第二次弹出对话框时,我得到“在模块 MSVCR110D.dll 中的地址访问冲突”,第三次,我得到“QCoreApplication 中的断言失败,应该只有一个应用程序对象” .所以我总是需要关闭整个应用程序才能使对话框再次出现,这大大减慢了工作速度。 如果我在底部添加该行

QApplication::quit()

对话框再次出现,但程序在关闭第二个对话框时崩溃。 加载dll的代码如下

HINSTANCE lib = ::LoadLibrary(L"RoboTechPolylineDialog.dll");
if(!lib)
{
    ShowMessage("Unable to load RoboTechPolylineDialog.dll");
    return;
}

typedef void ( *POPUP_ROBO_TECH_DIALOG )();
POPUP_ROBO_TECH_DIALOG fp = (POPUP_ROBO_TECH_DIALOG) ::GetProcAddress(lib, "popupRoboTechDialog"); 

if(!fp)
{
    ShowMessage("Unable to load function popupRoboTechDialog from RoboTechPolylineDialog.dll");
    ::FreeLibrary(lib);
    return;
}

(*fp)( );

FreeLibrary(lib);

那么,为什么我一次要构建多个 QApplication?我可以在上面的代码中替换行

(*fp)();

(*fp)();
(*fp)();

对话框出现两次,一切正常。但是对 ::FreeLibrary(lib) 的调用如何使事情失败。

谁能帮助我?任何帮助、解决方法等都非常感谢。

【问题讨论】:

  • 你只需要一个QApplication。尝试阅读此stackoverflow.com/questions/11054087/…
  • 我已经读过,但对我没有帮助。我看不到哪里有多个 QApplication(只有一个 Dll 使用 Qt,在这里我需要以某种方式正确关闭 QApplication。)
  • 我认为问题在于您多次调用 popupRoboTechDialog() 并且多次构建 QApplication。 Qt 更喜欢另一个工作流程,这就是为什么最好将 QApplication 移动到另一个地方
  • 那么一个合适的设计应该是什么样子的呢?我添加了我如何调用 popupRoboTechDialog 的代码。
  • 我猜第二个应用程序是您的访问冲突异常留下的,它是一个后续错误。您必须调试访问冲突。

标签: c++ qt dll qapplication qcoreapplication


【解决方案1】:

这应该可行:

#include <QApplication>
#include <QString>
#include <QDialog>

class App {
    QApplication *_app;
public:
    App(int argc = 0, char** argv = NULL)
        : _app(new QApplication(argc, argv))
    {

    }

    ~App() {
        delete _app;
    }
};

void dialog()
{
    static int argc = 1;
    static char *argv[] = {"Design polyline"};
    static App(argc, argv);
    QDialog dlg;
    dlg.exec();
}

void main()
{
    dialog();
    dialog();
    dialog();
}

【讨论】:

    【解决方案2】:

    另一个建议:从子路径加载 Qt 库,因为您可能会发现 dll 与在同一文件夹中使用它的其他应用程序发生冲突(个人经验)

    【讨论】:

    • 很棒的提示。但它是如何工作的。我试图加载 HINSTANCE lib = ::LoadLibrary(L"QtDlls\RoboTechPolylineDialog.dll") 但没有用。
    • 我的意思是从您的 RoboTechPolylineDialog.dll 中加载 Qt5GUI.dll 等
    • 即。许多 3dsmax 插件都在使用 Qt,因此它可能会导致您在版本之间陷入 dll 地狱,使这种加载方式您可以在不同的地方拥有自己的 .dll 以避免此问题。
    猜你喜欢
    • 2012-04-25
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多