【发布时间】:2015-03-27 04:46:25
【问题描述】:
总结:我有一个导出函数的 DLL。在这个函数中,我调用 QApplication::allWidgets() ,它返回一个空列表,而如果这个函数在应用程序中,则返回一个包含 19 个项目的列表。
如果我没记错的话,有一个由框架维护的静态项目列表。 allWidgets() 函数正在返回该列表。据我所知,DLL 应该与应用程序位于同一地址空间,这意味着我应该能够从 DLL 访问所有静态变量。那为什么函数在 DLL 和应用程序中会有所不同呢?
这是 DLL 代码:
------------------------ test.h ----
extern "C" TESTSHARED_EXPORT std::string DllFun();
------------ test.cpp --------------
std::string DllFun()
{
std::stringstream temp;
QList<QWidget *> list = QApplication::allWidgets();
temp << "Number of widgets from DLL " << list.size();
return temp.str();
}
这里是应用代码sn-p:
------------------ mainwindow.cpp -------------- --
std::string MainWindow::FunInternal()
{
std::stringstream temp;
QList<QWidget *> list = QApplication::allWidgets();
temp << "Number of widgets from Applicaton " << list.size();
return temp.str();
}
void MainWindow::on_pushButton_clicked()
{
typedef std::string (*FunType)();
HMODULE handle = LoadLibrary(L"Test.dll");
FunType DllFun = (FunType)GetProcAddress(handle, "DllFun");
if (Fun)
{
std::string DllWidgets = DllFun();
std::string InternalWidgets = FunInternal();
ui->textEdit->append(QString(DllWidgets.c_str()));
ui->textEdit->append(QString("\n"));
ui->textEdit->append(QString(InternalWidgets.c_str()));
}
}
当我点击按钮结果是:
来自 DLL 0 的小部件数量
Applicaton 19 中的小部件数量
我正在使用 Qt 5.2 Mingw 64 位。
更新:即使我的问题仍然有效,这是一个似乎有效的解决方法。如果我将函数指针传递给 DLL 并从 DLL 调用函数指针,它会返回 19 ,就像应用程序一样。
正如 Chris 所指出的,DLL 和 Application 似乎有两个独立的数据部分。 DLL 不能正常访问应用程序的数据部分(其中包含 GUI 的状态信息),除非通过数据接口或指向它的指针。就我而言,这是不可能的,因为我的界面是通用的。我试图通过在我的 DLL 中使用 GetProcAddress 来推动这一点,但我没有取得太大的成功,但我认为理论上这应该可行。
我目前的设计是这样的:
------- genwidget.h
class MyWidget
{
public:
void modifyWidget(HWND id);
}
------- qtwidget.cpp
#include <genwidget.h>
void MyWidget::modifyWidget(HWND id)
{
// find Panel widget
QWidget *widget = find_widget_from_list(id, QApplication::allWidgets())
// do work
}
------- vcwidget.cpp
#include <genwidget.h>
void MyWidget::modifyWidget(HWND id)
{
// find Panel widget
Panel ^widget = find_widget_from_list(id);
// do work
}
我认为我必须通过以下方式更改我的设计,以便为每个环境提供自己的界面。
------- genwidget.h
class MyWidget
{
public:
virtual void modifyWidget() = 0;
}
------- qtwidget.h
class QtMyWidget : public MyWidget
{
public:
QtMyWidget(QWidget *panel);
void modifyWidget();
}
------- vcwidget.h
class VcMyWidget : public MyWidget
{
public:
VcMyWidget(Panel ^panel);
void modifyWidget();
}
【问题讨论】:
-
在 DLL 中链接的版本与访问从未实例化的 QWidgetPrivate::allWidgets 变量的代码链接(除非您在 DLL 中创建 QApplication),但是,函数指针是传入的链接与创建 QApplication 时分配的 QWidgetPrivate::allWidgets 变量相关联。
-
我不确定我是否理解你。您是在建议解决方案吗?或者你是说它不起作用?如果您的解决方案是实例化一个新的 QApplication,那么我看不出它是如何工作的,因为这会给我一个新的 Widget 映射,其中不包含我感兴趣的小部件。
-
我基本上是在说你前进的方向是行不通的。我已经编辑了我将如何解决这个问题的解决方案。
-
我认为你在很大程度上是对的。我认为就我正在使用的 Qt5.2 构建而言,似乎有两个单独的数据部分。 DLL 和应用程序。但我认为这个故事还有更多内容,因为我不是在玩 Qt 4.7,而且我在 DLL 中,我的 allWidgets 返回的数字与它在应用程序中的数字相同。根据你的说法,这是不可能的。我的 Qt 4.7 构建是动态的,而 Qt 5.2 是静态的。这是唯一的重大变化。任何想法可能会发生什么?
-
我动态编译了Qt5.2。还有两个数据部分。因此静态或动态构建似乎不会导致 qt4.7 与 qt5.2 的差异。