Connecting C++ Qt widgets and PySide2 ones
-
I want to mix up these two into one QMainWindow with dynamically loaded docker widgets. Is there an official way of doing this?
From the point, that PySide2 and Qt are using same shared libraries I can assume that in depth of every PySide2 widget lies a native C++ one. If there's no way of integrating them with API, then how can I get the address of PySide2 widget?
I can pass this address from Python to C++ code, cast it to QWidget, change parent and so on. -
Hi and welcome to devnet,
You'll likely be interested in the Embedding Python part of this blog article.
-
@Denni-0 No, to support extensions/add-ons, which C++ do not know of at a compile time.
@SGaist That is almost exactly what I'm looking for. Furthermore, what I'm looking for could even be replaced by this approach. Appreciate it!
Initially, I was looking for a way to expose PySide2 widget to C++ code, but now I know how to expand existing Qt C++ class to PySide2 and allow modules to interact with it as a PySide2 object, that should suffice.
Would be great If you could give another hint : )In case someone will also look for the code:
https://code.qt.io/cgit/pyside/pyside-setup.git/tree/examples/scriptableapplication -
Do you mean generate Python bindings for your classes ?
-
@SGaist That's the first approach, to generate bindings via Shiboken and make C++ classes available via Python.
I'm looking for a way to export PySide2 widget to C++ code, e.g.
Let's assume we have embedded python module :PyMethodDef methods_def[] = { {"c_fun", c_func, METH_VARARGS, ""} } PyModuleDef module_def = { PyModuleDef_HEAD_INIT, "mm", nullptr, -1, methods_def, nullptr, nullptr, nullptr, nullptr }; PyObject * c_fun(PyObject * self, PyObject *args) { // Code where you get PyObject * widget_pyo from args QWidget * aws_wgt = reinterpret_cast<QWidget *>( PyLong_AsLong(widget_pyo) ); // Wrong aws_wgt->setWindowsTitle("h4x"); }
And the Python code will look like this:
from PySide2.QtWidget import QWidget import mm aws_wgt = QWidget() aws_wgt.resize(200, 200) aws_wgt.setWindowsTitle("Awesome widget") aws_wgt.show() mm..c_fun(aws_wgt)
And run it
PyObject * dict = PyDict_New(); PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins() ); PyRun_StringFlags(py_code, Py_file_input, dict, dict, nullptr);
-
I am not aware of such a way currently. I must say I don't see the point this way around. Making an application scriptable through python, sure, but taking actions on QWidget based python objects from C++ extensions seems a bit convoluted. Can you explain a use case for that ?
-
I believe the most cases I can come up with are already covered by Shiboken bindings.
The only thing that comes in mind is the speed (C++ runs faster, does not require thread state) and the object relationship.
If we export C++ Qt Object variable to python this object will be owned by python code. We cannot directly manipulate these PySide2 widgets from C++ code, only via signals/slots (with a particular assumption that PySide2 widgets will follow the required behavior).
For example, if we are not writing python code, and provide this feature to customers/users and it is required that each python widget must be explicitly registered for some C++ controller. We can expect that user will do this but we cannot be sure.
And the last point is that as I understand, this won't require shiboken since we don't need to generate Python bindings for C++ code, we need the PySide2 objects to open their insides for C++. -
@tellien
I'll say one thing: the rule of thumb is that UI will be so "slow" that Python vs C++ speed won't be relevant (even for output, which you do want fast, remember that even if you are PySide2 the actual Qt code running underneath will be the C++ Qt code in libraries, not Python).The difference between Python & C++ will be more noticeable in your code which factors enormous numbers into primes, or sorts a billion items, or launches rockets to The Moon, etc. :)
-
That makes sense, but that does not mean we should prefer PySide2 over Qt. I think we should allow users to choose between these two. And I think exporting raw QWidget pointer from PyObject should take place.
@SGaist From the point that PySide2 is using same symbols as regular C++ Qt applications I think it will not be too convoluted but as simple as returning a pointer with reinterpret_case<QWidget *> (which will be obtained somehow from SbkObject).
For users it will mean more freedom to choose where and how they want to use Qt classes and making communication between Python and C++ complete so they would have same interface for same objects.