Jim wrote:
Hi, I have been doing some wxWidgets work in C++ and driving it
with top level wxPython. Now I need my python code to react to events in the C++ world. I'm trying to use SWIG's directors, and they work, unless some other part of my extension does an %import core.i
The problem appears to be related to the fact that wxPython uses SWIG directives to wrap all calls to C/C++ functions with code that releases and reacquires the Python Global Interpreter Lock, in order to allow Python code in other threads to run while the C/C++ function is running. In _defs.i you;ll find this code:
%exception {
PyThreadState* __tstate = wxPyBeginAllowThreads();
$action
wxPyEndAllowThreads(__tstate);
if (PyErr_Occurred()) SWIG_fail;
}
When the GIL is released like this then any code inside of $action that manipulates PyObjects, (like building a list if items for a return value) or calls Python code (like an event handler or a virtual method callback) needs to acquire the GIL before it can do so. If not then Python will abort() if it is able or I've seen it just crash a couple times too.
So basically the problem is that when you %import core.i you are getting the above declaration and so all your function calls will release and reacquire the GIL when they run, but your virtual method callback wrappers generated by the swig director feature are not acquiring the GIL before they try to call the Python method in the derived class.
There are a few approaches to take to solve this.
* Rebuild wxPython with threads disabled by undefining WXP_WITH_THREAD. Not recommended as it will prevent other threads from running while any wx C/C++ code is running.
* Turn off the above declaration for your director based classes by using the empty %exception directive in your .i files. Care should be taken with this approach as well because if anything done in your virtual callbacks causes a wx event to be sent or wx callback to be called then the code there will expect that it needs to reacquire the GIL and it could cause a deadlock (although the risk of this is greatly reduced in Python 2.4+ because of the use of a newer Python API for ensuring that the GIL is acquired safely.)
* Add SWIG directives that will add code to the director functions that invoke the Python methods, such that the call to the Python function is wrapped in code like this:
wxPyBlock_t blocked = wxPyBeginBlockThreads();
...
wxPyEndBlockThreads(blocked);
Having not done more than experiment a bit with directors I'm not sure how to do that, but I expect that there is a way.
···
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!