pybind / pybind/pybind11

pybind11 + pySide2 crashes

Open
#2,216 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

Hello

1st of all thanks for awesome lib!

2nd I'm stuck with this issue, most of my other code works fine but this one... wrhhh

So the layout
I have c++ app with Qt as gui, I use QtWebEngine to embed a code editor for easier coding, none of it is much relevant to use but just in case. I'll try to "lay out" what/why I'm doing as maybe Its affecting something...

Now I added a py::scoped_interpreter guard; in my python handling class in header. This is a persistent copy of python that is meant to live the entire time app is alive. So Its put in constructur and kicks off. The 1st command I send to pybind is to push the print statement out of it so the code is as follow >


#include "pythonHandler.h"
#include "iostream"
#include "qdebug.h"
#include "simpleWindow.h"
#include "testManager.h"
#include "lib/globalHandler.h"

#ifdef _LIBPATH
#define TXT _LIBPATH
#else
#define TXT "unconfiguredEnviPath"
#endif
int tadd(int i, int j) {
    std::cout << i << j << std::endl;
    return i + j;
}

PYBIND11_EMBEDDED_MODULE(pyt, m) {
    m.doc() = "I do Nothing... yet?";
    m.def("xadd", &tadd, "A function which adds two numbers");
    //m.def("getGlobalHelper", &tadd, "A function which adds two numbers"); // they should return pointer to objects with these objects functions exposed.
    //m.def("getTestManager", &tadd, "A function which adds two numbers"); // they should return pointer to objects with these objects functions exposed.
    m.def("getTestManager", &testManager::TM, py::return_value_policy::reference);
    m.def("getGlobalHelper", &globalHandler::getGlobalHelper, py::return_value_policy::reference);
}


PYBIND11_EMBEDDED_MODULE(icPrint, m) {
    // `m` is a `py::module` which is used to bind functions and classes
    m.doc() = "Print helper class  manager classes"; // optional module docstring
    m.def("print_overrided", [](std::string log) {
        auto resultLog = QString(log.data());
        if (resultLog.length() > 0 && resultLog != "\n")
            simpleWindow::SW()->setReturnMessage(resultLog);
    });
}


pythonHandler *pythonHandler::icP() {
    static pythonHandler icp;
    return &icp;
}

pythonHandler::pythonHandler() {
    //guard = py::scoped_interpreter{};
    glob = py::globals();
    //loc = py::object();

    QString starter(R"(
from  icPrint import print_overrided
import io, sys,os
class StdoutCatcher(io.TextIOBase):
    def __init__(self):
        self.data = []
    def write(self, stuff):
        print_overrided(stuff)
sys.stdout = StdoutCatcher()

default_value = "crap"
val = "$replacePathEnv"
print(val)

sys.path.insert(0, val)
sys.path.insert(0, val+"Lib")
sys.path.insert(0, val+"DLLs")
sys.path.insert(0, val+"lib\site-packages")
for a in sys.path:
    print(a)

if not hasattr(sys, 'argv'):
    sys.argv  = ['']
        )");
    QString envi(TXT);
    envi = envi + "python/active/";
    qDebug() << "Envi path : " << envi;
    std::cout << " envi path " << envi.toStdString().c_str() << std::endl;
    starter = starter.replace("$replacePathEnv", envi);
    try {
        py::exec(starter.toStdString().c_str(), glob);
    }
    catch (const std::exception &e) {
        QString error(e.what());
        simpleWindow::SW()->setReturnMessage(error);
    }
}

pythonHandler::~pythonHandler() {
}

void pythonHandler::runCommand(QString text) {

    try {
        py::exec(text.toStdString().c_str(), glob);
    }
    catch (const std::exception &e) {
        QString error(e.what());
        simpleWindow::SW()->setReturnMessage(error);
    }
}

So once the class is initialized it pushes out print back to c++ to be displayed in my editor and I send commands to it from editor. So far so good, I can send as much commands as I want provided I'm not working with pyside2. I did not check other libraries yet...

So the problem starts here, when I run this command >

from PySide2.QtWidgets import *
app = QApplication([""])
w = QWidget()
w.show()
sys.exit(app.exec_())

1st run is fine, but second run cause
image
image

And here I'm lost... what do I do with it ? :- )

One thing that I wonder about is if I should somehow pass my c++Qt QApplication instead of making new one? I'm not sure, at some point I'd like to make a widget in python that interacts with c++ widget so... hmmm ? ideas?

Regards
Dariusz

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the embedded interpreter lifecycle in pythonHandler::pythonHandler and runCommand, using the PySide2 command shown in the issue to reproduce the second-run crash. Inspect how the persistent interpreter and QApplication are created and reused; done means identifying a reproducible lifecycle cause and documenting the required ownership or usage change.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
desktop, devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.