Exceptions from callbacks
Eric Dorland
dorland at lords.com
Wed Nov 3 20:16:15 EST 1999
Randall Hopper wrote:
> I've done this, and I got the impression that Jonathan understood your
> question. What he described works and it's what I'm using.
>
> To extend your description, you don't say "Wake up, Python!" from the
> callback. You say it from the C function(s) from which you entered the C
> library that invoked the callback. Return NULL, and the exception is
> restarted with the Python stack frames saved in the callback in-tow.
>
> To make this concrete, for a C library API that might potentially invoke a
> callback (which in-turn would relay to Python) would look like this:
>
> (Python) -> HandlePendingMessages -> MYLIB -> Callback -> (Python)
>
> And your wrapper code might look like this:
>
> ------------------------------------------------------------------------------
> PyObject *_wrap_MYLIBHandlePendingMessages( PyObject *self, PyObject *args )
> {
> PyErr_Clear();
>
> <<< call C function here >>>
>
> /* If a Python callback threw an exception, restart its propagation */
> /* in the controlling Python. */
> if ( PyErr_Occurred() )
> return NULL;
>
> ...
> }
>
> ------------------------------------------------------------------------------
> static void _wrap_MYLIBCallback( void )
> /* C callback used to relay to Python callable objects. */
> {
> ...
>
> /* Pass the buck onto Python */
> pyresult = PyEval_CallObject( pyfunc, pyargs ); /* Call Python */
> Py_DECREF( pyargs ); /* Trash arg list */
> if ( pyresult )
> Py_DECREF( pyresult ); /* Trash any result*/
>
> /* If the callback threw an exception, it will be propagated across */
> /* the C layer ( we check PyErr_Occurred() on the other side). */
> }
> ------------------------------------------------------------------------------
>
> If the Python callback tossed an exception, then it's still lying around
> when _wrap_MYLIBCallback() returns. We then return through the C library,
> which eventually returns to _wrap_MYLIBHandlePendingMessages, who
> recognizes that a Python exception is pending and restarts its propagation
> in the controlling Python stack frames.
>
> Note that if you have a C library layer that isn't Python-exception-aware,
> then it could go on to perform useless or invalid work after a Python
> callback throws an exception. In this case you'll need to "make" it aware.
> That is, have it call PyErr_Occurred(), or turn Python exceptions into C
> library errors inside of your callback wrappers.
>
> Hope this clarifies things a bit.
I understand what you mean exactly. The problem is I can't do it that
way. Basically, the way the library works is that you register a bunch
of callbacks and then call a function (eg. Loop()) that doesn't return.
The HandlePendingEvents (its equivalent I mean :)) isn't exposed by the
library, so I can't wrap it :). That's way I want a way to force the
interpreter to realize an exception is there. Is there a way, or a work
around, to do this?
--
Eric Dorland
dorland at lords.com
More information about the Python-list
mailing list