[PyKDE] embedding PyQt in a c++ app
Christoph Wiedemann
wiedeman at gmx.net
Mon Aug 2 18:18:00 BST 2004
> Hi.
>
> On Thu, Jul 29, 2004 at 05:21:25PM +0200, Christoph Wiedemann wrote:
> > Hello,
> >
> > i have problems to embed PyQt in a c++ application. Since the
> application
> > uses threads and multiple python interpreters, i must ensure that the
> > correct thread state is set and the GIL is locked, whenever the python
> API
> > is used. I do that with the
> >
> > PyEval_RestoreThread(threadState);
> >
> > and
> >
> > PyEval_SaveThread();
> >
> > methods. This works fine, as long as i don't use widgets created with
> PyQt,
> > because there are many "callbacks" (virtual methods), e.g.
> mousePressEvent,
> > which are called directly from PyQt.
> >
>
> I had the same problem. But since this wasn't a major issue for my
> project, I gave up without investigating. But I am interested in the
> solution.
>
> > Is there any way to force PyQt to acquire the GIL before those virtual
> > methods are called?
> >
> > Hmm, this wouldn't solve the issue with multiple interpreters; each
> > interpreter has its own thread state, which must be restored before
> using
> > the API.
>
> I do it something like that:
>
> PyThreadState* _pyThreadState;
> _pyThreadState = Py_NewInterpreter();
>
> then later
>
> PyEval_AcquireLock();
> PyThreadState_Swap(_pyThreadState);
>
> ... some python stuff ...
>
> PyThreadState_Swap(NULL);
> PyEval_ReleaseLock();
>
> and when I'm done
>
> PyEval_AcquireLock();
> PyThreadState_Swap(_pyThreadState);
>
> Py_EndInterpreter(_pyThreadState);
>
> PyThreadState_Swap(NULL);
> PyEval_ReleaseLock();
I think i got a solution for that. The trick is to call
PyThreadState_Swap(threadState);
in the QWidget.event function (when this function is called, the GIL is
already hold). This is done by some c-extension stuff, so i can do the
following:
class MyWidget(QWidget):
def event(self, e):
support.swapThreadState() # calls appropriate c-function
return QWidget.event(self, e)
and everything works out fine (at least for instances of MyWidget).
I'm still not sure, if i can apply the same trick for built-in widgets; i
don't need them by now, but maybe later. I guess i can't do
b = QButton()
oldEvent = b.event
def myEvent(self, e):
support.swapThreadState()
return oldEvent(self, e)
b.event = myEvent
??
Maybe it's enough to put all builtin-widgets into a self-written container
widget with the event handler installed...
Thanks,
Christoph
More information about the PyQt
mailing list