simplify the thread implementation, use feature 'nothread' to disable threads instead of 'thread' to enable them, plus other fixes around threads

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7933 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2005-12-06 19:35:03 +00:00
commit 2eeef5275d
6 changed files with 62 additions and 101 deletions

View file

@ -23,47 +23,30 @@ Version 1.3.28 (unreleased).
%module("threads"=1) %module("threads"=1)
2.- For each method you want to add full thread support, you 2.- Equivalent to that, is the following swig option
should use the "threads" feature, as in
%feature("threads") method;
or in the directive form
%threads method;
3.- Since threads is a feature, you can enable it for the
entire interface as follow
%module("threads"=1)
%threads;
4.- Equivalent to that, is the following swig option
swig -threads -python ... swig -threads -python ...
ie, swig enables thread support for the module and all ie, swig enables thread support for the module.
the methods.
5.- You can partially disable thread support for each 3.- You can partially disable thread support for a given
method using: method using:
%feature("nothreads") method; %feature("nothread") method;
also, you can disable sections of the thread support, also, you can disable sections of the thread support,
for example for example
%feature("nothreadsblock") method; %feature("nothreadblock") method;
%feature("nothreadsallow") method; %feature("nothreadallow") method;
the first disable the C++/python thread protection, and the the first disables the C++/python thread protection, and the
second the python/C++ thread protection. See second disables the python/C++ thread protection.
pythreads.swg for more information.
6.- The current thread support is based in the PyGIL 4.- The current thread support is based in the PyGIL
extension present in python version 2.3 or later, but extension present in python version 2.3 or later, but
you can provide the thread code for older versions by you can provide the thread code for older versions by
defining the macros described in pythreads.swg. defining the macros in pythreads.swg.
If you get a working implementation for older versions, If you get a working implementation for older versions,
please send us a patch. please send us a patch.

View file

@ -8,7 +8,6 @@ class Foo;
extern "C" void* working(void* t); extern "C" void* working(void* t);
%} %}
%threads;
%director Foo; %director Foo;
%inline { %inline {

View file

@ -643,7 +643,6 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
if (pyobj && PySwigObject_Check(pyobj)) { if (pyobj && PySwigObject_Check(pyobj)) {
return (PySwigObject *) pyobj; return (PySwigObject *) pyobj;
} else { } else {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyObject *obj = 0; PyObject *obj = 0;
#ifndef SWIG_PYTHON_SLOW_GETSET_THIS #ifndef SWIG_PYTHON_SLOW_GETSET_THIS
if (PyInstance_Check(pyobj)) { if (PyInstance_Check(pyobj)) {
@ -664,13 +663,11 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
#endif #endif
if (!obj || PyErr_Occurred()) { if (!obj || PyErr_Occurred()) {
PyErr_Clear(); PyErr_Clear();
SWIG_PYTHON_THREAD_END_BLOCK;
return 0; return 0;
} }
if (!PySwigObject_Check(obj)) { if (!PySwigObject_Check(obj)) {
obj = 0; obj = 0;
} }
SWIG_PYTHON_THREAD_END_BLOCK;
return (PySwigObject *)obj; return (PySwigObject *)obj;
} }
} }
@ -828,11 +825,9 @@ SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
if (!ptr) { if (!ptr) {
return SWIG_Py_Void(); return SWIG_Py_Void();
} else if (!type) { } else if (!type) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj"); PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj");
} }
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL; return NULL;
} else { } else {
int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
@ -872,7 +867,6 @@ void *SWIG_ReturnGlobalTypeList(void *);
SWIGRUNTIME swig_module_info * SWIGRUNTIME swig_module_info *
SWIG_Python_GetModule(void) { SWIG_Python_GetModule(void) {
static void *type_pointer = (void *)0; static void *type_pointer = (void *)0;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
/* first check if module already created */ /* first check if module already created */
if (!type_pointer) { if (!type_pointer) {
#ifdef SWIG_LINK_RUNTIME #ifdef SWIG_LINK_RUNTIME
@ -886,7 +880,6 @@ SWIG_Python_GetModule(void) {
} }
#endif #endif
} }
SWIG_PYTHON_THREAD_END_BLOCK;
return (swig_module_info *) type_pointer; return (swig_module_info *) type_pointer;
} }
@ -898,27 +891,21 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
{ {
PyObject *dict; PyObject *dict;
if (!PyModule_Check(m)) { if (!PyModule_Check(m)) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"PyModule_AddObject() needs module as first arg"); "PyModule_AddObject() needs module as first arg");
SWIG_PYTHON_THREAD_END_BLOCK;
return SWIG_ERROR; return SWIG_ERROR;
} }
if (!o) { if (!o) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"PyModule_AddObject() needs non-NULL value"); "PyModule_AddObject() needs non-NULL value");
SWIG_PYTHON_THREAD_END_BLOCK;
return SWIG_ERROR; return SWIG_ERROR;
} }
dict = PyModule_GetDict(m); dict = PyModule_GetDict(m);
if (dict == NULL) { if (dict == NULL) {
/* Internal error -- modules must have a dict! */ /* Internal error -- modules must have a dict! */
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
PyModule_GetName(m)); PyModule_GetName(m));
SWIG_PYTHON_THREAD_END_BLOCK;
return SWIG_ERROR; return SWIG_ERROR;
} }
if (PyDict_SetItemString(dict, name, o)) if (PyDict_SetItemString(dict, name, o))

View file

@ -1,24 +1,22 @@
#if defined(SWIG_PYTHON_NO_THREADING) #if defined(SWIG_PYTHON_NO_THREADS)
# if defined(SWIG_PYTHON_THREADING) # if defined(SWIG_PYTHON_THREADS)
# undef SWIG_PYTHON_THREADING # undef SWIG_PYTHON_THREADS
# endif # endif
#endif #endif
#if defined(SWIG_PYTHON_THREADING) /* Threading support is enabled */ #if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */
# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) # if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL)
# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ # if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */
# define SWIG_PYTHON_USE_GIL # define SWIG_PYTHON_USE_GIL
# endif # endif
# endif # endif
# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ # if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */
# if !defined(SWIG_PYTHON_INITIALIZE_THREADING) # define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads()
# define SWIG_PYTHON_INITIALIZE_THREADING PyEval_InitThreads() # ifdef __cplusplus /* C++ code */
# endif
# ifdef __cplusplus
class SWIG_Python_Thread_Block { class SWIG_Python_Thread_Block {
bool status; bool status;
PyGILState_STATE state; PyGILState_STATE state;
public:
void begin() { if (!status) { state = PyGILState_Ensure(); status = true;} } void begin() { if (!status) { state = PyGILState_Ensure(); status = true;} }
public:
void end() { if (status) { PyGILState_Release(state); status = false;} } void end() { if (status) { PyGILState_Release(state); status = false;} }
SWIG_Python_Thread_Block() : status(false) { begin(); } SWIG_Python_Thread_Block() : status(false) { begin(); }
~SWIG_Python_Thread_Block() { end(); } ~SWIG_Python_Thread_Block() { end(); }
@ -26,8 +24,8 @@
class SWIG_Python_Thread_Allow { class SWIG_Python_Thread_Allow {
bool status; bool status;
PyThreadState *save; PyThreadState *save;
public:
void begin() { if (!status) { status = true; save = PyEval_SaveThread(); } } void begin() { if (!status) { status = true; save = PyEval_SaveThread(); } }
public:
void end() { if (status) { PyEval_RestoreThread(save); status = false; }} void end() { if (status) { PyEval_RestoreThread(save); status = false; }}
SWIG_Python_Thread_Allow() : status(false) { begin(); } SWIG_Python_Thread_Allow() : status(false) { begin(); }
~SWIG_Python_Thread_Allow() { end(); } ~SWIG_Python_Thread_Allow() { end(); }
@ -36,15 +34,15 @@
# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() # define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end()
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow # define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow
# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() # define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end()
# else /* C++ */ # else /* C code */
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_allow = PyGILState_Ensure() # define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure()
# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_allow) # define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block)
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW Py_BEGIN_ALLOW_THREADS # define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread()
# define SWIG_PYTHON_THREAD_END_ALLOW Py_END_ALLOW_THREADS # define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow)
# endif # endif
# else /* Old thread way, not implemented, user must provide it */ # else /* Old thread way, not implemented, user must provide it */
# if !defined(SWIG_PYTHON_INITIALIZE_THREADING) # if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
# define SWIG_PYTHON_INITIALIZE_THREADING # define SWIG_PYTHON_INITIALIZE_THREADS
# endif # endif
# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) # if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK # define SWIG_PYTHON_THREAD_BEGIN_BLOCK
@ -60,7 +58,7 @@
# endif # endif
# endif # endif
#else /* No thread support */ #else /* No thread support */
# define SWIG_PYTHON_INITIALIZE_THREADING # define SWIG_PYTHON_INITIALIZE_THREADS
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK # define SWIG_PYTHON_THREAD_BEGIN_BLOCK
# define SWIG_PYTHON_THREAD_END_BLOCK # define SWIG_PYTHON_THREAD_END_BLOCK
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW # define SWIG_PYTHON_THREAD_BEGIN_ALLOW

View file

@ -1,15 +1,15 @@
/* ----------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* Special user directives * Special user directives
* ----------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* shadow code */ /* shadow code */
#define %shadow %insert("shadow") #define %shadow %insert("shadow")
#define %pythoncode %insert("python") #define %pythoncode %insert("python")
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
Use the "nondynamic" feature to make a wrapped class behaves as a "nondynamic" Use the "nondynamic" feature to make a wrapped class behaves as a "nondynamic"
one, ie, a python class that doesn't dynamically add new attributes. one, ie, a python class that doesn't dynamically add new attributes.
@ -51,7 +51,7 @@ so, it works with old python versions.
#define %pythondynamic %nopythonnondynamic #define %pythondynamic %nopythonnondynamic
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
Use %pythonmaybecall to flag a method like __add__ or __radd__, which Use %pythonmaybecall to flag a method like __add__ or __radd__, which
@ -65,7 +65,7 @@ These methods "may be called" if needed.
#define %nopythonmaybecall %feature("python:maybecall", "0") #define %nopythonmaybecall %feature("python:maybecall", "0")
#define %clearpythonmaybecall %feature("python:maybecall", "") #define %clearpythonmaybecall %feature("python:maybecall", "")
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
The %pythoncallback feature produce a more natural callback wrap The %pythoncallback feature produce a more natural callback wrap
than the %callback mechanism, ie, it use the original name for than the %callback mechanism, ie, it use the original name for
@ -111,7 +111,7 @@ These methods "may be called" if needed.
#define %nopythoncallback %feature("python:callback","0") #define %nopythoncallback %feature("python:callback","0")
#define %clearpythoncallback %feature("python:callback","") #define %clearpythoncallback %feature("python:callback","")
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
Support for the old %callback directive name Support for the old %callback directive name
*/ */
@ -131,14 +131,15 @@ These methods "may be called" if needed.
#define %nocallback %nopythoncallback #define %nocallback %nopythoncallback
#define %clearcallback %clearpythoncallback #define %clearcallback %clearpythoncallback
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
Thread support Thread support - Advance control
*/ */
#define %threads %feature("threads") #define %nothread %feature("nothread")
#define %nothreads %feature("threads","0") #define %thread %feature("nothread","0")
#define %clearthreads %feature("threads","") #define %clearnothread %feature("nothread","")
#define %nothreadblock %feature("nothreadblock") #define %nothreadblock %feature("nothreadblock")
#define %threadblock %feature("nothreadblock","0") #define %threadblock %feature("nothreadblock","0")
@ -149,7 +150,7 @@ These methods "may be called" if needed.
#define %clearnothreadallow %feature("nothreadallow","") #define %clearnothreadallow %feature("nothreadallow","")
/* ----------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
Directors Directors
*/ */

View file

@ -58,6 +58,7 @@ static String *real_classname;
/* Thread Support */ /* Thread Support */
static int threads = 0; static int threads = 0;
static int nothreads = 0;
/* flags for the make_autodoc function */ /* flags for the make_autodoc function */
enum autodoc_t { enum autodoc_t {
@ -115,7 +116,7 @@ public:
* ------------------------------------------------------------ */ * ------------------------------------------------------------ */
int threads_enable(Node *n) const { int threads_enable(Node *n) const {
return threads && GetFlagAttr(n, "feature:threads"); return threads && !GetFlagAttr(n, "feature:nothread");
} }
int initialize_threads(String *f_init) { int initialize_threads(String *f_init) {
@ -124,7 +125,7 @@ public:
} }
Printf(f_init,"\n"); Printf(f_init,"\n");
Printf(f_init,"/* Initialize threading */\n"); Printf(f_init,"/* Initialize threading */\n");
Printf(f_init,"SWIG_PYTHON_INITIALIZE_THREADING;\n"); Printf(f_init,"SWIG_PYTHON_INITIALIZE_THREADS;\n");
return SWIG_OK; return SWIG_OK;
} }
@ -133,9 +134,9 @@ public:
if (!GetFlag(n, "feature:nothreadblock")) { if (!GetFlag(n, "feature:nothreadblock")) {
String *bb = Getattr(n,"feature:threadbeginblock"); String *bb = Getattr(n,"feature:threadbeginblock");
if (bb) { if (bb) {
Wrapper_add_local(f,"python_thread_state", bb); Append(f->code, bb);
} else { } else {
Wrapper_add_local(f,"python_thread_state", "SWIG_PYTHON_THREAD_BEGIN_BLOCK"); Append(f->code,"SWIG_PYTHON_THREAD_BEGIN_BLOCK;\n");
} }
} }
} }
@ -237,20 +238,11 @@ public:
Preprocessor_define((DOH *) "SWIG_NORTTI", 0); Preprocessor_define((DOH *) "SWIG_NORTTI", 0);
Swig_mark_arg(i); Swig_mark_arg(i);
} else if (strcmp(argv[i],"-threads") == 0) { } else if (strcmp(argv[i],"-threads") == 0) {
Hash *features_hash = Swig_cparse_features();
String *name = NewString("");
String *fname = NewString("feature:threads");
String *fvalue = NewString("1");
Swig_feature_set(features_hash,name,0,fname,fvalue,0);
threads = 1; threads = 1;
Swig_mark_arg(i); Swig_mark_arg(i);
Delete(name);
Delete(fname);
Delete(fvalue);
} else if (strcmp(argv[i],"-nothreads") == 0) { } else if (strcmp(argv[i],"-nothreads") == 0) {
/* Turn off thread suppor mode */ /* Turn off thread suppor mode */
threads = 0; nothreads = 1;
Preprocessor_define((DOH *) "SWIG_PYTHON_NO_THREADING", 0);
Swig_mark_arg(i); Swig_mark_arg(i);
} else if (strcmp(argv[i],"-modern") == 0) { } else if (strcmp(argv[i],"-modern") == 0) {
apply = 0; apply = 0;
@ -375,8 +367,10 @@ public:
Printf(f_runtime,"#define SWIG_DIRECTORS\n"); Printf(f_runtime,"#define SWIG_DIRECTORS\n");
} }
if (threads) { if (nothreads) {
Printf(f_runtime,"#define SWIG_PYTHON_THREADING\n"); Printf(f_runtime,"#define SWIG_PYTHON_NO_THREADS\n");
} else if (threads) {
Printf(f_runtime,"#define SWIG_PYTHON_THREADS\n");
} }
/* Set module name */ /* Set module name */
@ -1550,18 +1544,17 @@ public:
Printf(f->code, " Swig::UnknownExceptionHandler dh;\n"); Printf(f->code, " Swig::UnknownExceptionHandler dh;\n");
} else { } else {
Printf(f->code, "{\n"); Printf(f->code, "{\n");
if (allow_thread) thread_begin_allow(n, f);
} }
if (allow_thread) thread_begin_allow(n, f);
emit_action(n,f); emit_action(n,f);
if (allow_thread) thread_end_allow(n, f);
if (director_method) { if (director_method) {
Printf(f->code, "} catch (Swig::DirectorException&) {\n"); Printf(f->code, "} catch (Swig::DirectorException&) {\n");
Printf(f->code, " SWIG_fail;\n"); Printf(f->code, " SWIG_fail;\n");
Printf(f->code, "}\n"); Printf(f->code, "}\n");
} else { } else {
if (allow_thread) thread_end_allow(n, f);
Printf(f->code, "}\n"); Printf(f->code, "}\n");
} }
@ -3011,23 +3004,26 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
} }
int allow_thread = threads_enable(n); int allow_thread = threads_enable(n);
if (allow_thread) thread_begin_block(n, w);
/* direct call to superclass if _up is set */ /* direct call to superclass if _up is set */
Printf(w->code, "if (swig_get_up()) {\n"); Printf(w->code, "if (swig_get_up()) {\n");
if (allow_thread) thread_end_block(n, w);
if (pure_virtual) { if (pure_virtual) {
Printf(w->code, Printf(w->code,
"Swig::DirectorPureVirtualException::raise(\"%s.\");\n",Swig_method_call(super,l)); "Swig::DirectorPureVirtualException::raise(\"%s.\");\n",Swig_method_call(super,l));
} else { } else {
if (allow_thread) thread_begin_allow(n, w);
if (is_void) { if (is_void) {
Printf(w->code, "%s;\n", Swig_method_call(super,l)); Printf(w->code, "%s;\n", Swig_method_call(super,l));
Printf(w->code, "return;\n"); Printf(w->code, "return;\n");
} else { } else {
Printf(w->code, "return %s;\n", Swig_method_call(super,l)); Printf(w->code, "return %s;\n", Swig_method_call(super,l));
} }
if (allow_thread) thread_end_allow(n, w);
} }
Printf(w->code, "}\n"); Printf(w->code, "} else {\n");
if (allow_thread) thread_begin_block(n, w);
/* wrap complex arguments to PyObjects */ /* wrap complex arguments to PyObjects */
Printv(w->code, wrap_args, NIL); Printv(w->code, wrap_args, NIL);
@ -3040,13 +3036,11 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
Printf(w->code, "if (!swig_get_self()) {\n"); Printf(w->code, "if (!swig_get_self()) {\n");
if (allow_thread) thread_end_block(n, w);
Printf(w->code, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname); Printf(w->code, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname);
Printf(w->code, "}\n"); Printf(w->code, "}\n");
Wrapper_add_local(w, "method", "PyObject* method = 0"); Wrapper_add_local(w, "method", "PyObject* method = 0");
Printf(w->code, "method = swig_get_method(swig_method_index, swig_method_name);\n"); Printf(w->code, "method = swig_get_method(swig_method_index, swig_method_name);\n");
Printf(w->code, "if (method == NULL) {\n"); Printf(w->code, "if (method == NULL) {\n");
if (allow_thread) thread_end_block(n, w);
Printf(w->code, " Swig::DirectorMethodException::raise(\"Method '%s.%s' doesn't exist\");\n", classname, pyname); Printf(w->code, " Swig::DirectorMethodException::raise(\"Method '%s.%s' doesn't exist\");\n", classname, pyname);
Printf(w->code, "}\n"); Printf(w->code, "}\n");
@ -3072,18 +3066,15 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
Printf(w->code, "if (result == NULL) {\n"); Printf(w->code, "if (result == NULL) {\n");
Printf(w->code, " PyObject *error = PyErr_Occurred();\n"); Printf(w->code, " PyObject *error = PyErr_Occurred();\n");
if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
if (allow_thread) thread_end_block(n, w);
Replaceall(tm, "$error", "error"); Replaceall(tm, "$error", "error");
Printv(w->code, Str(tm), "\n", NIL); Printv(w->code, Str(tm), "\n", NIL);
} else { } else {
Printf(w->code, " if (error != NULL) {\n"); Printf(w->code, " if (error != NULL) {\n");
if (allow_thread) thread_end_block(n, w);
Printf(w->code, " Swig::DirectorMethodException::raise(\"Error detected when calling %s.%s\");\n", Printf(w->code, " Swig::DirectorMethodException::raise(\"Error detected when calling %s.%s\");\n",
classname, pyname); classname, pyname);
Printf(w->code, " }\n"); Printf(w->code, " }\n");
} }
Printf(w->code, "}\n"); Printf(w->code, "}\n");
if (allow_thread) thread_end_block(n, w);
Delete(tm); Delete(tm);
/* /*
@ -3170,6 +3161,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
} }
/* any existing helper functions to handle this? */ /* any existing helper functions to handle this? */
if (allow_thread) thread_end_block(n, w);
if (!is_void) { if (!is_void) {
String* rettype = SwigType_str(return_type, 0); String* rettype = SwigType_str(return_type, 0);
if (!SwigType_isreference(return_type)) { if (!SwigType_isreference(return_type)) {
@ -3180,6 +3172,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
Delete(rettype); Delete(rettype);
} }
Printf(w->code, "}\n");
Printf(w->code, "}\n"); Printf(w->code, "}\n");
/* emit the director method */ /* emit the director method */