I'd like to use PySide to define the basic QT classes and the mapping between C++ and python, but to do so in both standalone python code and from embedded python using boost::python.
First, the module definition and class returning QPointF:
QPointF X::getY() {
return QPointF();
}
BOOST_PYTHON_MODULE(myBoostPythonModule)
{
// is there some magic init/register commands to put here?
boost::python::api::object module = import("__main__");
boost::python::api::object name_space = module.attr("__dict__");
boost::python::exec("from PySide.QtCore import *",name_space,name_space);
boost::python::exec("import sys,os\nprint(sys.modules)",name_space,name_space);
class_<X, boost::noncopyable>(
"X", init<const char*>())
.def("getY",&X::getY)
;
}
Now, the application's embedded python code, last line is what fails and I'm wondering how to get around:
execute("import myBoostPythonModule"); // OK
execute("x=myBoostPythonModule.X('foo')"); // OK
execute("w=QPointF()\nprint(w)"); // OK
// PySide.QtCore.QPointF(0.000000, 0.000000)
execute("y=x.getY()"); // FAIL:
// TypeError: No to_python (by-value) converter found for C++ type: QPointF
What's going on here, I can create a QPointF, but the name somehow isn't bound between python and c++ ? Am I missing some imports in the module to tell it to import from PySide?
PySide provides its Qt bindings with Shiboken. Shiboken generates Python C API bindings that supporting its own type conversion system. The knowledge of these conversions resides within the Shiboken generated bindings, and not the Python type system. Thus, PySide knows how to convert a
QPointF
object to/from C++/Python; Python's type system does not.When an object transitions through a function exposed with Boost.Python, then Boost.Python will check its registry for the appropriate type converter. These converters provide Boost.Python with knowledge on how to convert to/from C++/Python for types exposed through Boost.Python. Hence, when Boost.Python tries to return a
QPointF
C++ type to Python, it throws an exception as the conversion has not been registered with Boost.Python.Here is the annotated code:
It is possible to implement Boost.Python's converters in terms of another implementation. Expanding upon the Shiboken type converter example, below is a complete example of Boost.Python's converters implemented with Shiboken's old type converter. I would have used the new Shiboken type converter API, but it was unclear to me as to what it is based on the documentation.
And its usage:
Alternative, while not the most elegant of approaches, one could have the functions exposed from Boost.Python use
boost::python::object
types, and interface with the object via Python statements. Something similar to:The above code will have Python instantiate a
QPointF
Python object, which will delegate to Shiboken's type system. AsX::getY()
returns a generic object, Boost.Python will not attempt to perform type conversions when the object handle transitions from C++ to Python.Based on the earlier replies and other info I've found, here's a somewhat general routine to allow things like
PySide.QtGui.QColor
argument to get passed into aboost::python
wrapped c++ method that expects aQColor&
input argument:and, calling the above from a startup function: