-
Notifications
You must be signed in to change notification settings - Fork 107
Closed
Description
OS: Windows11 24H2
Python Version: 3.13
Qt Version: 6.8
PythonQt Version: 3.6
Compiler: msvc
I do two tests about receiving return value from python.
The first one is running well:
/// Test 1: Python Class
qDebug() << "Test 1: Python Class";
{
QVariant pyobj = context.evalScript("TestPyObj()", Py_eval_input); /// The TestPyObj Class is defined by Python Code
qDebug() << pyobj;
if(pyobj.isValid()) {
PythonQtObjectPtr pyobj_ptr(pyobj);
qDebug() << "PyObj RefCount:" << pyobj_ptr->ob_refcnt; ///2 pyobj & pyobj_ptr
pyobj.clear();
qDebug() << "PyObj RefCount:" << pyobj_ptr->ob_refcnt; ///1 pyobj
pyobj_ptr.call("print");
}
/// destroyed
}But if I change the TestPyObj Class to TestCppObj which is defined in Cpp code and registered to Python by PythonQt, the return value will be destroyed directly before the cpp code receive it. The Test Code is below
///... init code
PythonQt::self()->registerCPPClass("TestCppObj", "", "TestUtils", PythonQtCreateObject<TestCppObjWrapper>, PythonQtSetInstanceWrapperOnShell<TestCppObjShell>);
///... other code
qDebug() << "Test 2: C++ Class";
{
QVariant pyobj = context.evalScript("pqt.TestUtils.TestCppObj()", Py_eval_input);
qDebug() << pyobj;
if(pyobj.isValid()) {
}
}The printed messages are:
Test 2: C++ Class
TestCPPObj created 2258935037504
TestCppObjShell created 2258935037504
TestCppObjShell destroyed 2258935037504
TestCPPObj destroyed 2258935037504
QVariant(void*, 0x20df3053e40) /// 0x20df3053e40 ==2258935037504
The class decleration is below:
/// Class
class TestCppObj {
public:
TestCppObj() {
std::cout << "TestCPPObj created " << size_t(this) << std::endl;
}
virtual ~TestCppObj() {
std::cout << "TestCPPObj destroyed " << size_t(this) << std::endl;
}
virtual void print() {
std::cout << "Hello from C++" << std::endl;
}
};
/// Shell Class
class TestCppObjShell : public TestCppObj {
public:
TestCppObjShell(): _wrapper(nullptr) {
std::cout << "TestCppObjShell created " << size_t(this) << std::endl;
}
~TestCppObjShell() {
std::cout << "TestCppObjShell destroyed " << size_t(this) << std::endl;
PythonQtPrivate* priv = PythonQt::priv();
if (priv) { priv->shellClassDeleted(this); }
}
void print() override {
std::cout << "Shell Print" << std::endl;
if (_wrapper) {
PYTHONQT_GIL_SCOPE;
if(((PyObject*)_wrapper)->ob_refcnt > 0) {
static PyObject* name = PyString_FromString("print");
PyObject* obj = PyBaseObject_Type.tp_getattro((PyObject*)_wrapper, name);
if (obj) {
static const char* argumentList[] ={""};
static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(1, argumentList);
void* args[1] = {nullptr};
PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);
if (result) { Py_DECREF(result); }
Py_DECREF(obj);
return;
} else {
PyErr_Clear();
}
}
}
TestCppObj::print();
}
PythonQtInstanceWrapper* _wrapper { nullptr };
};
/// Wrapper Class
class TestCppObjWrapper : public QObject {
Q_OBJECT
public slots:
TestCppObj* new_TestCppObj() {
return new TestCppObjShell ();
}
void delete_TestCppObj(TestCppObj* obj) {
delete obj;
}
void print(TestCppObj* obj) {
obj->print();
}
};Thanks for any help.
Metadata
Metadata
Assignees
Labels
No labels