Proper use of wxPyBeginBlockThreads/wxPyEndBlockThreads

I'm not sure what the proper use of
wxPyBeginBlockThreads/wxPyEndBlockThreads is. I have a method (listed
below) that is creating and returning a python list. From what I read
in the Wiki, I should be calling
wxPyBeginBlockThreads/wxPyEndBlockThreads if I am doing any manipulation
of Python objects. However, if I uncomment these calls then I get a
consistent segfault when wxPyBeginBlockThreads is called. The wrapper
statement from the .i is also listed below.

So my question is: Do I need to wrap this code in
wxPyBeginBlockThreads/wxPyEndBlockThreads?

Any other comments on this are also welcome. I'm new to messing with
Python stuff in C.

PyObject *wxPseudoDC::FindObjectsByBBox(wxCoord x, wxCoord y)
{
    //wxPyBlock_t blocked = wxPyBeginBlockThreads();
    PyObject* pyList = NULL;
    pyList = PyList_New(0);
<snip>
            PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
            PyList_Insert(pyList, 0, pyObj);
            Py_DECREF(pyObj);
<snip>
    //wxPyEndBlockThreads(blocked);
    return pyList;
}

DocDeclStr(PyObject*, FindObjectsByBBox(wxCoord x, wxCoord
y),"<snip>","");

Lanier, Paul wrote:

I'm not sure what the proper use of
wxPyBeginBlockThreads/wxPyEndBlockThreads is. I have a method (listed
below) that is creating and returning a python list. From what I read
in the Wiki, I should be calling
wxPyBeginBlockThreads/wxPyEndBlockThreads if I am doing any manipulation
of Python objects. However, if I uncomment these calls then I get a
consistent segfault when wxPyBeginBlockThreads is called. The wrapper
statement from the .i is also listed below.

So my question is: Do I need to wrap this code in
wxPyBeginBlockThreads/wxPyEndBlockThreads?

Yes, although there can be exceptions to the rule. [1]

What you pasted into your message looks correct, and I don't see any problems with it as is. You may want to use the debugger to trace into the wxPyBeginBlockThreads() call though to verify that the API is loaded correctly. It's actually a macro that gets a pointer to a structure of function pointers, and then calls the function via the function pointer. The structure is imported from the wx._core_ module by the wxPyCoreAPI_IMPORT function the first time the API is used in each of the other modules, so that is a point of failure you may want to check.
There is a commented-out wxASSERT in wxPyGetCoreAPIPtr in wxPython.h that you can comment-in to help you diagnose this if needed.

Another point of failure can happen if the API stuct that is imported is different than the one defined in the wxPython header files you are using for compiling. This can result in the wrong function being called, possibly corrupting the stack by expecting a different number of parameters on the stack, etc. One way this could happen is if you have a wxPython.h you are compiling with that doesn't match the one used to compile the wx._core_ module that is being imported.

[1] If the wrapper function generated by SWIG doesn't release the GIL then there is no need to acquire it and release it again with the wxPyBeginBlockThreads/wxPyEndBlockThreads calls. Any swig file that imports wxPython's core.i module (or ones that import it) should automatically wrap the function call with code that releases the GIL, but in 2.7 there are ways to turn that off if desired. You can do it for a specific function by using the KeepGIL(name) macro before the function is declared, like this

  KeepGIL(FindObjectsByBBox);
  DocDeclStr(PyObject*, FindObjectsByBBox(wxCoord x, wxCoord y), "","");

Or you can turn it on or off globally for a block of class/function/method declarations, like this

  %threadWrapperOff;
  ... Some declarations ...
  %threadWrapperOn;

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!