[PyKDE] embedding python widgets in C++ app

Phil Thompson phil at riverbankcomputing.co.uk
Mon Jan 22 10:46:07 GMT 2007


On Monday 22 January 2007 9:21 am, Patrick Stinson wrote:
> oops, I think the title is backwards. I will send the author an email.
> I am trying to embed a python widget in a C++ application, where he is
> trying to access his C++ app code from his python code.
>
> I decided to manually import a module with a factory function, call
> that factory function from C++ and convert the python object to a
> QWidget * using sipConvertToInstance. After doing this, I have a few
> questions:
>
> What should the transfer object be as passed to sipConvertToInstance?
> I'm a little confused about the wording in the documentation, and
> sipTransferObj is automatically included if you are using this in a
> sip file.

It depends on what you are going to do with the C++ instance (when is the dtor 
going to be called) and it's Python object (when is it going to be garbage 
collected). Do you want the C++ instance to outlive the Python object?

> How are you supposed to statically link the PyQt libraries if you then
> lose the PyQt4 package, which initQtGui() expects to import QtCore
> from? initQtCore() works fine but initQtGui() fails looking for
> PyQt4.QtGui.

PyQt modules are modules - they are not libraries. You do not link against 
them. You can configure them as builtin modules, just like any other module.

> Any comments on the following code?
>
>   char nameBuf[2048];
>   strcpy(nameBuf, moduleName);
>   PyObject *module = PyImport_ImportModule(nameBuf);
>   if(module)
>     {
>       PyObject *_create = PyObject_GetAttrString(module, "_create");
>       if(_create)
>         {
>           if(PyCallable_Check(_create))
>             {
>               PyObject *sipPy = PyObject_Call(_create,
> Py_BuildValue("()"), NULL);
>               if(sipPy)
>                 {
>                   int iserr = 0;
>                   QWidget *widget = reinterpret_cast<QWidget
> *>(sipConvertToInstance(sipPy, sipClass_QWidget, NULL, SIP\
> _NO_CONVERTORS, 0, &iserr));
>                   if(iserr == 0 && widget)
>                     {
>                       widget->show();
>                       qDebug("GOT WIDGET %p", widget);
>                       ret = widget;
>                     }
>                   else
>                     qWarning("could not sip => widget");
>                 }
>               else
>                 qWarning("error in _create return (%p)", sipPy);
>             }
>           else
>             qWarning("error \"_create\" is not callable");
>           Py_DECREF(_create);
>         }
>       else
>         qWarning("no attribute \"_create\"");
>     }
>   else
>     qWarning("no module \"pktest\"");

Obviously you are leaking the sipPy and widget instances.

The above code has to be part of a SIP generated module that %Imports 
PyQt4.QtGui. The SIP API can only be called from SIP generated modules.

Phil




More information about the PyQt mailing list