gpt4 book ai didi

PyQt4 看不到 C++ 实例化的 QApplication

转载 作者:太空狗 更新时间:2023-10-29 23:17:42 26 4
gpt4 key购买 nike

我有一个 C++/Qt 应用程序,它使用 QPluginLoader 工具加载一个插件 (.dll/.so)。这个插件基本上是一个嵌入式 python 解释器,它允许通过 PyQt4 模块检查主应用程序中的 Qt 对象。

问题是从插入的 python 解释器执行的命令 PyQt4.QtCore.QCoreApplication.instance() 返回 None,即使 QCoreApplication 实例已由 C++ 应用程序创建。

这仅适用于处于 Debug模式的 Windows。

在 linux 或 windows 的 Release模式下,命令 PyQt4.QtCore.QCoreApplication.instance() 正确返回由 C++ 应用程序创建的 QCoreApplication 实例。

以下是一些显示问题的极简代码。

在 Release模式下编译时:

$ ./a.out
1+1
2
import PyQt4
import PyQt4.QtCore
PyQt4.QtCore.QCoreApplication.instance()
<PyQt4.QtCore.QCoreApplication object at 0x00C69198>

=> 好的

在 Debug模式下编译时:

$ ./a.out
import PyQt4
import PyQt4.QtCore
PyQt4.QtCore.QCoreApplication.instance()

=> 不正常(返回 None)

文件 main.cpp

#include <QCoreApplication>
#include <QPluginLoader>
#include <QDebug>

int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);

QPluginLoader loader("plugin.dll");
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
loader.load();
if(!loader.isLoaded()) {
qDebug() << loader.errorString();
return 1;
}
(void)loader.instance();

return app.exec();
}

文件plugin.h

#ifndef PLUGIN_H
#define PLUGIN_H

#include <QObject>
#include <Python.h>

class Plugin : public QObject
{
public:
Plugin();
~Plugin();

private:
PyThreadState *m_ts;
};

class InterpInput : public QObject
{
Q_OBJECT
public:
InterpInput(QObject *parent = 0) : QObject(parent) { }
public slots:
void monitorInput();
signals:
void done();
void inputReady();
};

class InterpOutput : public QObject
{
Q_OBJECT
public:
InterpOutput(QObject *parent = 0) : QObject(parent) { }
public slots:
void processLine();
public:
PyThreadState *m_ts;
};

#endif

文件 plugin.cpp

#include "plugin.h"

#include <QCoreApplication>
#include <QThread>
#include <QtPlugin>
#include <QPluginLoader>

Q_EXPORT_PLUGIN2(Plugin, Plugin)

Plugin::Plugin()
{
Py_Initialize();
PyEval_InitThreads();

InterpInput *in = new InterpInput();
InterpOutput *out = new InterpOutput(this);
in->connect(in, SIGNAL(inputReady()), out, SLOT(processLine()));
in->connect(in, SIGNAL(done()), QCoreApplication::instance(), SLOT(quit()));

QThread *thr = new QThread(this);
in->moveToThread(thr);
thr->connect(thr, SIGNAL(started()), in, SLOT(monitorInput()));

m_ts = PyEval_SaveThread();
out->m_ts = m_ts;

thr->start();
}

Plugin::~Plugin()
{
PyEval_RestoreThread(m_ts);
Py_Finalize();
}

void InterpInput::monitorInput()
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

int ret = PyRun_SimpleString("import sys\nimport code\nic = code.InteractiveConsole()");
assert(ret == 0);
while(true) {
ret = PyRun_SimpleString("line = ic.raw_input()");
if(ret) { break; }
inputReady();
}
done();

PyGILState_Release(gstate);
}

void InterpOutput::processLine()
{
PyEval_RestoreThread(m_ts);
int ret = PyRun_SimpleString("ic.push(line)");
PyRun_SimpleString("sys.stdout.flush()");
PyRun_SimpleString("sys.stderr.flush()");
(void)PyEval_SaveThread();
assert(ret == 0);
}

文件生成文件

MOC=/cygdrive/c/Qt/4.8.4/bin/moc
GCC=/cygdrive/c/MinGW/bin/mingw32-g++.exe
FLAGS=-Ic:/Qt/4.8.4/include -Ic:/Qt/4.8.4/include/QtCore -Lc:/Qt/4.8.4/lib -Lc:/Qt/4.8.4/bin -lQtCore4 -Lc:/Python27/libs -lpython27 -Ic:/Python27/include -DQT_NO_DEBUG
#FLAGS=-Ic:/Qt/4.8.4/include -Ic:/Qt/4.8.4/include/QtCore -Lc:/Qt/4.8.4/bin -lQtCored4 -Lc:/Python27/libs -lpython27 -Ic:/Python27/include -g
LIBFLAGS=-shared

all:
$(MOC) plugin.h > plugin_moc.cpp
$(GCC) -o a.out main.cpp $(FLAGS)
$(GCC) -o plugin.dll $(LIBFLAGS) plugin.cpp plugin_moc.cpp $(FLAGS)

最佳答案

解释如下。

在调试版本中,C++ 应用程序和插件链接到调试 Qt 库(QtCored4.dll 等)而安装的 PyQt4 模块(QtCore.pyd 等)链接到发布 Qt 库(QtCore4.dll 等)

因此,C++ 应用程序和 PyQt4 模块每个都看到一个 QCoreApplication 实例,但每个都看到一个不同的实例,它位于不同的库中(分别是 Qt 库的调试和发布版本)。

因此,PyQt4 模块中的实例在 C++ 应用程序初始化时并未初始化,因此为 null。

这通过编译指定它们应链接到调试 Qt 库的 PyQt4 模块来验证:随着 Debug模式 C++ 应用程序和 PyQt4 模块链接到同一个 Qt 库,问题就会消失。

关于PyQt4 看不到 C++ 实例化的 QApplication,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16743509/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com