On Fri, 24 Mar 2006 17:40:00, Eric Jardim wrote: > I found a way of getting Python extended widgets. > > I will post here the way I did and I would like to know if this is the > right, easy and safer way of doing this:
I've added comments below. > Supose this is a QWidget subclass and that I wrote a module called " > MyWidget.py" with "MyWidget" class defined inside of it. > > // let's assume that I've already created my QApplication in C++ code. > SomeQWidgetClass::someMethod() > { > Py_Initialize(); > PyObject* __main__ = PyImport_AddModule("__main__"); > PyObject* scope = PyObject_GetAttrString(__main__, "__dict__"); > PyRun_String("import sip", Py_single_input, scope, scope); > PyRun_String("from PyQt4 import QtGui", Py_single_input, scope, scope); > PyRun_String("import MyWidget", Py_single_input, scope, scope); I usually import a module and execute code within that rather than within the __main__ module, using a factory function to do the work. I've removed a lot of the details from my code snippets. > // passing this widget as parent > QString cmd = QString( > "w = MyWidget.MyWidget(sip.wrapinstance(%1, > QtGui.SomeQWidgetClass))" ).arg((long)this); > PyObject* w = PyRun_String(cmd.toStdString().c_str(), Py_single_input, > scope, scope); > if (!w) > { > PyErr_Print(); > } > > PyObject* id = PyRun_String("sip.unwrapinstance(w)", Py_eval_input, > scope, scope); It's easy to define a single function to do this: PyRun_String("from PyQt4 import QtGui\nimport sip\n" "def __embedded_factory__create__(parent = None):\n" " global plugin\n" " print \""CLASS_NAME"\"\n" " plugin = "CLASS_NAME"(parent)\n" " return sip.unwrapinstance(plugin)\n", Py_file_input, pyDict, pyDict); PyObject *pyFactory = PyDict_GetItemString(pyDict, "__embedded_factory__create__"); This one creates a single instance of a plugin, typically an instance of a SIP-wrapped class. > QWidget* widget = (QWidget*) PyLong_AsLong(id); > layout()->addWidget(widget); > widget->show(); > } Obviously, this code doesn't do the same sort of thing, but it shows how I use the unwrapped instance returned by the Python function: PyObject *pyPluginPtr = call_function(pyFactory, 0); DesignerCustomWidgetPlugin *plugin = 0; if (pyPluginPtr) { // Extract the C++ pointer from the PyObject. plugin = static_cast<DesignerCustomWidgetPlugin*>( PyLong_AsVoidPtr(pyPluginPtr)); // Decrement the reference count of the long value. Py_XDECREF(pyPluginPtr); } else { qDebug() << "Failed"; } The plugin is an instance of a SIP-wrapped class, so it handles all the ownership issues. > Another thing I am worried about is memory management. Is there any special > care that should I take with those Python created objects? I'm worried about this, too, and I don't really know how to deal with multiple instances returned to my C++ code that I pass on to the application. I guess I should transfer ownership of them to C++. However, if I just wrap single-instance plugins that are supposed to exist for the application's running lifetime, this issue is mostly avoided. A while ago, I uploaded an example of widget embedding to this page: http://www.boddie.org.uk/david/Projects/Python/Qt/ Reviewing it recently, I'm not sure that it's really all that helpful, but you might get some ideas from it. David _______________________________________________ PyKDE mailing list PyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde