fixes for directors + pointers

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7860 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2005-11-21 21:01:35 +00:00
commit f3c24eff33
16 changed files with 808 additions and 137 deletions

View file

@ -1,6 +1,29 @@
Version 1.3.28 (unreleased).
===========================
11/21/2005: mmatus
[ruby + python]
Fixes for directors + pointers, ugly problem with not easy
solution. Before we identified this case as problematic:
virtual const MyClass& my_method();
but it turns out that all the cases where a pointer, array or
reference is returned, are problematic, even for
primitive types (as int, double, char*, etc).
To try to fix the issue, a new typemap was added,
'directorfree', which is used to 'free' the resources
allocated during the 'directorout' phase. At the same
time, a primitive garbage collector engine was added to
deal with orphans addresses, when needed.
The situation now is much better, but still you can have
memory exaustation if recursion is used.
So, still you need to avoid returning pointers, arrays or
references when using director methods.
11/14/2005: wsfulton
More types added to windows.i, eg UINT8, WORD, BYTE etc.
Including windows.i will also enable SWIG to parse the __declspec Microsoft
@ -69,26 +92,25 @@ Version 1.3.28 (unreleased).
instance (not as in C++), only the last base class was
properly deletted, or detected with directors.
Now the self.this element can be a list, which will
contain the C++ instance pointers for all the base
classes.
Now 'self.this' can be a list, which will contain the C++
instance pointers for all the base classes.
- Now the 'this' pointer is responsible for deallocating
the C++ instance, and the __del__ method is not emitted
unless the user preppend/append some code to it.
Also, swig.this is responsible for deallocating the C++
instance(s), and the __del__ method is not emitted unless
the user preppend/append some code to it.
- Swig now can detect memory leaks, ie, if you still
use the non-shadow module, and type something like
- Swig now can detect memory leaks, ie, if you still
use the non-shadow module, and type something like
import _example
f = _example.new_Foo()
and forgot to call _example.delete_Foo(f), then swig
will tell you that there is a memory leak.
and forgot to call _example.delete_Foo(f), then swig will
tell you that there is a memory leak.
Otherwise, if you always use the shadow module, probably
you will never ever see this warning unless there is
something wrong inside the swig wrapping code.
Otherwise, if you always use the shadow module, probably
you will never ever see this warning unless there is
something wrong inside the swig wrapping code.
*** POTENTIAL INCOMPATIBILITY ***

View file

@ -10,15 +10,30 @@
#ifdef __cplusplus
namespace Swig {
GCItem::~GCItem()
{
}
/* simple thread abstraction for pthreads on win32 */
Director::~Director() {
swig_decref();
}
/* wrap a python object, optionally taking ownership */
Director::Director(PyObject* self) : swig_self(self), swig_disown_flag(false) {
#ifdef __PTHREAD__
MUTEX_INIT(swig_mutex_own);
#endif
swig_incref();
}
bool Director::swig_up = false;
#ifdef __PTHREAD__
MUTEX_INIT(Director::swig_mutex_up);
pthread_mutex_t SWIG_MUTEX_INIT(Director::swig_mutex_up);
pthread_t Director::swig_mutex_thread;
bool Director::swig_mutex_active = false;
#endif

View file

@ -14,6 +14,22 @@
#include <string>
#include <iostream>
#include <exception>
#include <vector>
#include <map>
/*
Use -DSWIG_DIRECTOR_NOVTABLE if you don't want to generate a 'virtual
table', and avoid multiple GetAttr calls to retreive the python
methods.
*/
#ifndef SWIG_DIRECTOR_NOVTABLE
#ifndef SWIG_DIRECTOR_VTABLE
#define SWIG_DIRECTOR_VTABLE
#endif
#endif
/*
@ -50,6 +66,7 @@
# ifndef SWIG_DIRECTOR_RTDIR
# define SWIG_DIRECTOR_RTDIR
#include <map>
namespace Swig {
class Director;
SWIGINTERN std::map<void*,Director*>& get_rtdir_map() {
@ -85,6 +102,117 @@ extern "C" {
namespace Swig {
/* memory handler */
struct GCItem
{
virtual ~GCItem() = 0;
virtual int get_own() const
{
return 0;
}
};
struct GCItem_var
{
GCItem_var(GCItem *item = 0) : _item(item)
{
}
GCItem_var& operator=(GCItem *item)
{
GCItem *tmp = _item;
_item = item;
delete tmp;
return *this;
}
~GCItem_var()
{
delete _item;
}
GCItem * operator->() const
{
return _item;
}
private:
GCItem *_item;
};
struct GCItem_Object : GCItem
{
GCItem_Object(int own) : _own(own)
{
}
virtual ~GCItem_Object()
{
}
int get_own()
{
return _own;
}
private:
int _own;
};
template <typename Type>
struct GCItem_T : GCItem
{
GCItem_T(Type *ptr) : _ptr(ptr)
{
}
virtual ~GCItem_T()
{
delete _ptr;
}
private:
Type *_ptr;
};
template <typename Type>
struct GCArray_T : GCItem
{
GCArray_T(Type *ptr) : _ptr(ptr)
{
}
virtual ~GCArray_T()
{
delete[] _ptr;
}
private:
Type *_ptr;
};
/* unknown exception handler */
class UnknownExceptionHandler
{
static void handler();
public:
#ifdef SWIG_DIRECTOR_UEH
std::unexpected_handler old;
UnknownExceptionHandler(std::unexpected_handler nh = handler)
{
old = std::set_unexpected(nh);
}
~UnknownExceptionHandler()
{
std::set_unexpected(old);
}
#endif
};
/* base class for director exceptions */
class DirectorException {
protected:
@ -120,25 +248,6 @@ namespace Swig {
}
};
/* unknown exception handler */
class UnknownExceptionHandler
{
static void handler();
public:
#ifdef SWIG_DIRECTOR_UEH
std::unexpected_handler old;
UnknownExceptionHandler(std::unexpected_handler nh = handler)
{
old = std::set_unexpected(nh);
}
~UnknownExceptionHandler()
{
std::set_unexpected(old);
}
#endif
};
/* type mismatch in the return value from a python method call */
class DirectorTypeMismatchException : public Swig::DirectorException {
@ -194,20 +303,41 @@ namespace Swig {
};
/* simple thread abstraction for pthreads on win32 */
/* simple thread abstraction for pthreads on win32 */
#ifdef __THREAD__
#define __PTHREAD__
#if defined(_WIN32) || defined(__WIN32__)
#define pthread_mutex_lock EnterCriticalSection
#define pthread_mutex_unlock LeaveCriticalSection
#define pthread_mutex_t CRITICAL_SECTION
#define MUTEX_INIT(var) CRITICAL_SECTION var
# define __PTHREAD__
# if defined(_WIN32) || defined(__WIN32__)
# define pthread_mutex_lock EnterCriticalSection
# define pthread_mutex_unlock LeaveCriticalSection
# define pthread_mutex_t CRITICAL_SECTION
# define SWIG_MUTEX_INIT(var) var
# endif
#else
#include <pthread.h>
#define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER
#endif
# include <pthread.h>
# define SWIG_MUTEX_INIT(var) var = PTHREAD_MUTEX_INITIALIZER
#endif
#ifdef __PTHREAD__
# define SWIG_GUARD(mutex) Guard _guard(mutex)
#else
# define SWIG_GUARD(mutex)
#endif
struct Guard
{
pthread_mutex_t *_mutex;
Guard(pthread_mutex_t &mutex) : _mutex(&mutex)
{
pthread_mutex_lock(_mutex);
}
~Guard()
{
pthread_mutex_unlock(_mutex);
}
};
/* director base class */
class Director {
@ -248,9 +378,7 @@ namespace Swig {
public:
/* wrap a python object, optionally taking ownership */
Director(PyObject* self) : swig_self(self), swig_disown_flag(false) {
swig_incref();
}
Director(PyObject* self);
/* discard our reference at destruction */
virtual ~Director();
@ -321,6 +449,53 @@ namespace Swig {
virtual void swig_set_inner(const char* /* name */, bool /* val */) const {
}
/* ownership managing */
private:
typedef std::map<void*, GCItem_var> ownership_map;
mutable ownership_map owner;
mutable pthread_mutex_t swig_mutex_own;
public:
template <typename Type>
void swig_acquire_ownership_array(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCArray_T<Type>(vptr);
}
}
template <typename Type>
void swig_acquire_ownership(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCItem_T<Type>(vptr);
}
}
void swig_acquire_ownership_obj(void *vptr, int own) const
{
if (vptr && own) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCItem_Object(own);
}
}
int swig_release_ownership(void *vptr) const
{
int own = 0;
if (vptr) {
SWIG_GUARD(swig_mutex_own);
ownership_map::iterator iter = owner.find(vptr);
if (iter != owner.end()) {
own = iter->second->get_own();
owner.erase(iter);
}
}
return own;
}
};
}

View file

@ -106,6 +106,13 @@ namespace swig {
Hence, this class is purely internal and not visible at the wrapped side.
*/
namespace swig {
%ignore PyObject_var;
struct PyObject_var {};
%apply PyObject * {PyObject_var};
%apply PyObject * const& {PyObject_var const&};
}
%{
namespace swig {
struct PyObject_var : PyObject_ptr {

View file

@ -44,7 +44,7 @@ namespace swig {
template <>
struct traits_check<PyObject_ptr, value_category> {
static bool check(PyObject *) {
static bool check(PyObject_ptr) {
return true;
}
};
@ -60,6 +60,41 @@ namespace swig {
}
%fragment(SWIG_Traits_frag(swig::PyObject_var),"header",fragment="StdTraits") {
namespace swig {
template <> struct traits<PyObject_var > {
typedef value_category category;
static const char* type_name() { return "PyObject_var"; }
};
template <> struct traits_from<PyObject_var> {
typedef PyObject_var value_type;
static PyObject *from(const value_type& val) {
PyObject *obj = static_cast<PyObject *>(val);
Py_XINCREF(obj);
return obj;
}
};
template <>
struct traits_check<PyObject_var, value_category> {
static bool check(PyObject_var) {
return true;
}
};
template <> struct traits_asval<PyObject_var > {
typedef PyObject_var value_type;
static int asval(PyObject *obj, value_type *val) {
if (val) *val = obj;
return SWIG_OK;
}
};
}
}
%fragment("PySequence_Base","header")
{
@ -79,6 +114,15 @@ namespace std {
operator()(const swig::PyObject_ptr& v, const swig::PyObject_ptr& w) const
{ return PyObject_Compare(v, w) < 0; }
};
template <>
struct less <swig::PyObject_var>: public binary_function<swig::PyObject_var, swig::PyObject_var, bool>
{
bool
operator()(const swig::PyObject_var& v, const swig::PyObject_var& w) const
{ return PyObject_Compare(v, w) < 0; }
};
}
namespace swig {
@ -706,7 +750,7 @@ namespace swig
%fragment("PySequence_Cont");
%newobject iterator(PyObject *PYTHON_SELF);
%newobject iterator(PyObject **PYTHON_SELF);
%extend {
swig::PySequence_OutputIterator* iterator(PyObject **PYTHON_SELF) {
return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);

View file

@ -11,16 +11,19 @@
/* Common SWIG API */
/* for raw pointers */
#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags)
#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags)
#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src)
#define swig_owntype int
/* for raw packed data */
#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type)
/* for class or struct pointers */
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags)
#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags)
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
/* for C or C++ function pointers */
#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
@ -282,7 +285,7 @@ SWIGINTERN PyObject*
PySwigObject_acquire(PyObject *v)
{
PySwigObject *sobj = (PySwigObject *)v;
sobj->own = 1;
sobj->own = SWIG_POINTER_OWN;
Py_INCREF(Py_None);
return Py_None;
}
@ -642,7 +645,7 @@ SWIG_This()
SWIGRUNTIMEINLINE PySwigObject *
SWIG_Python_GetSwigThis(PyObject *pyobj)
{
if (PySwigObject_Check(pyobj)) {
if (pyobj && PySwigObject_Check(pyobj)) {
return (PySwigObject *) pyobj;
} else {
PyObject *obj = 0;
@ -663,17 +666,37 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
obj = PyObject_GetAttr(pyobj,SWIG_This());
Py_XDECREF(obj);
#endif
if (PyErr_Occurred()) {
obj = 0;
if (!obj || PyErr_Occurred()) {
PyErr_Clear();
return 0;
}
if (PySwigObject_Check(obj)) {
return (PySwigObject *)obj;
} else {
return 0;
}
}
}
/* Acquire a pointer value */
SWIGRUNTIME int
SWIG_Python_AcquirePtr(PyObject *obj, int own) {
if (own) {
PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
if (sobj) {
int oldown = sobj->own;
sobj->own = own;
return oldown;
} else {
return 0;
}
return obj && PySwigObject_Check(obj) ? (PySwigObject *) obj : 0;
}
}
/* Convert a pointer value */
SWIGRUNTIME int
SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
if (!obj) return SWIG_ERROR;
if (obj == Py_None) {
*ptr = 0;
@ -703,6 +726,7 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags)
}
}
if (sobj) {
if (own) *own = sobj->own;
if (flags & SWIG_POINTER_DISOWN) {
sobj->own = 0;
}
@ -717,7 +741,7 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags)
SWIGRUNTIME int
SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
if (!PyCFunction_Check(obj)) {
return SWIG_Python_ConvertPtr(obj, ptr, ty, 0);
return SWIG_ConvertPtr(obj, ptr, ty, 0);
} else {
const char *desc = 0;
void *vptr = 0;
@ -814,7 +838,8 @@ SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
}
return NULL;
} else {
PyObject *robj = PySwigObject_New((void *) ptr, type, (flags & SWIG_POINTER_OWN));
int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
PyObject *robj = PySwigObject_New((void *) ptr, type, own);
PySwigClientData *clientdata = (PySwigClientData *)type->clientdata;
if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
@ -914,8 +939,7 @@ SWIG_Python_DestroyModule(void *vptr)
ty->clientdata = 0;
}
}
Py_DECREF(SWIG_This());
/* and, what else ... */
Py_DECREF(SWIG_This());
}
SWIGRUNTIME void

View file

@ -39,11 +39,11 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
*alloc = SWIG_NEWOBJ;
}
else {
*cptr = cstr;
*cptr = PyString_AsString(obj);
*alloc = SWIG_OLDOBJ;
}
} else {
*cptr = cstr;
*cptr = PyString_AsString(obj);
}
}
if (psize) *psize = len + 1;

View file

@ -9,17 +9,144 @@
* Mark Rose (mrose@stm.lbl.gov).
************************************************************************/
/*
Use -DSWIG_DIRECTOR_NOUEH if you prefer to avoid the use of the
Undefined Exception Handler provided by swift
*/
#ifndef SWIG_DIRECTOR_NOUEH
#ifndef SWIG_DIRECTOR_UEH
#define SWIG_DIRECTOR_UEH
#endif
#endif
#ifdef __cplusplus
#include <string>
#include <iostream>
#include <map>
namespace Swig {
/* memory handler */
struct GCItem
{
virtual ~GCItem() = 0;
virtual ruby_owntype get_own() const
{
return 0;
}
};
struct GCItem_var
{
GCItem_var(GCItem *item = 0) : _item(item)
{
}
GCItem_var& operator=(GCItem *item)
{
GCItem *tmp = _item;
_item = item;
delete tmp;
return *this;
}
~GCItem_var()
{
delete _item;
}
GCItem * operator->() const
{
return _item;
}
private:
GCItem *_item;
};
template <typename Type>
struct GCItem_T : GCItem
{
GCItem_T(Type *ptr) : _ptr(ptr)
{
}
virtual ~GCItem_T()
{
delete _ptr;
}
private:
Type *_ptr;
};
struct GCItem_Object : GCItem
{
GCItem_Object(ruby_owntype own) : _own(own)
{
}
virtual ~GCItem_Object()
{
}
ruby_owntype get_own()
{
return _own;
}
private:
ruby_owntype _own;
};
template <typename Type>
struct GCArray_T : GCItem
{
GCArray_T(Type *ptr) : _ptr(ptr)
{
}
virtual ~GCArray_T()
{
delete[] _ptr;
}
private:
Type *_ptr;
};
/* body args */
struct body_args {
VALUE recv;
ID id;
int argc;
VALUE *argv;
};
/* unknown exception handler */
class UnknownExceptionHandler
{
static void handler();
public:
#ifdef SWIG_DIRECTOR_UEH
std::unexpected_handler old;
UnknownExceptionHandler(std::unexpected_handler nh = handler)
{
old = std::set_unexpected(nh);
}
~UnknownExceptionHandler()
{
std::set_unexpected(old);
}
#endif
};
/* Base class for director exceptions */
class DirectorException {
@ -52,9 +179,15 @@ namespace Swig {
VALUE getError() const {
return swig_error;
}
const std::string& getMessage() const
{
return swig_msg;
}
virtual ~DirectorException() {}
};
/* Type mismatch in the return value from a Ruby method call */
class DirectorTypeMismatchException : public Swig::DirectorException {
public:
@ -123,6 +256,27 @@ namespace Swig {
#endif
#endif
#ifdef __PTHREAD__
# define SWIG_GUARD(mutex) Guard _guard(mutex)
#else
# define SWIG_GUARD(mutex)
#endif
struct Guard
{
pthread_mutex_t *_mutex;
Guard(pthread_mutex_t &mutex) : _mutex(&mutex)
{
pthread_mutex_lock(_mutex);
}
~Guard()
{
pthread_mutex_unlock(_mutex);
}
};
/* director base class */
class Director {
private:
@ -212,6 +366,55 @@ namespace Swig {
swig_disown_flag = true;
}
}
/* ownership managing */
private:
typedef std::map<void*, GCItem_var> ownership_map;
mutable ownership_map owner;
mutable pthread_mutex_t swig_mutex_own;
public:
template <typename Type>
void swig_acquire_ownership_array(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCArray_T<Type>(vptr);
}
}
template <typename Type>
void swig_acquire_ownership(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCItem_T<Type>(vptr);
}
}
void swig_acquire_ownership_obj(void *vptr, ruby_owntype own) const
{
if (vptr && own) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCItem_Object(own);
}
}
ruby_owntype swig_release_ownership(void *vptr) const
{
ruby_owntype own = 0;
if (vptr) {
SWIG_GUARD(swig_mutex_own);
ownership_map::iterator iter = owner.find(vptr);
if (iter != owner.end()) {
own = iter->second->get_own();
owner.erase(iter);
}
}
return own;
}
};
bool Swig::Director::swig_up = false;
@ -222,6 +425,34 @@ namespace Swig {
bool Swig::Director::swig_mutex_active = false;
#endif
void UnknownExceptionHandler::handler() {
try {
throw;
} catch (DirectorException& e) {
std::cerr << "Swig Director exception caught:" << std::endl
<< e.getMessage() << std::endl;
} catch (std::exception& e) {
std::cerr << "std::exception caught: "<< e.what() << std::endl;
} catch (...) {
std::cerr << "Unknown exception caught." << std::endl;
}
std::cerr << std::endl
<< "Ruby interpreter traceback:" << std::endl;
std::cerr << std::endl;
std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl
<< "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl
<< std::endl
<< "Exception is being re-thrown, program will like abort/terminate." << std::endl;
throw;
}
GCItem::~GCItem()
{
}
}
#endif /* __cplusplus */

View file

@ -8,20 +8,23 @@
************************************************************************/
/* for raw pointers */
#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Ruby_ConvertPtr(obj, pptr, type, flags)
#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Ruby_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Ruby_ConvertPtrAndOwn(obj, pptr, type, flags, own)
#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Ruby_NewPointerObj(ptr, type, flags)
#define SWIG_AcquirePtr(ptr, own) SWIG_Ruby_AcquirePtr(ptr, own)
#define swig_owntype ruby_owntype
/* for raw packed data */
#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Ruby_ConvertPacked(obj, ptr, sz, ty, flags)
#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Ruby_NewPackedObj(ptr, sz, type)
/* for class or struct pointers */
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_Ruby_ConvertPtr(obj, pptr, type, flags)
#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_Ruby_NewPointerObj(ptr, type, flags)
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
/* for C or C++ function pointers */
#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Ruby_ConvertPtr(obj, pptr, type, 0)
#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Ruby_NewPointerObj(ptr, type, 0)
#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_ConvertPtr(obj, pptr, type, 0)
#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NewPointerObj(ptr, type, 0)
/* for C++ member pointers, ie, member methods */
#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Ruby_ConvertPacked(obj, ptr, sz, ty)
@ -162,9 +165,23 @@ SWIG_Ruby_MangleStr(VALUE obj)
return StringValuePtr(stype);
}
/* Acquire a pointer value */
typedef void (*ruby_owntype)(void*);
SWIGRUNTIME ruby_owntype
SWIG_Ruby_AcquirePtr(VALUE obj, ruby_owntype own) {
if (obj) {
ruby_owntype oldown = RDATA(obj)->dfree;
RDATA(obj)->dfree = own;
return oldown;
} else {
return 0;
}
}
/* Convert a pointer value */
SWIGRUNTIME int
SWIG_Ruby_ConvertPtr(VALUE obj, void **ptr, swig_type_info *ty, int flags)
SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags, ruby_owntype *own)
{
char *c;
swig_cast_info *tc;
@ -186,6 +203,8 @@ SWIG_Ruby_ConvertPtr(VALUE obj, void **ptr, swig_type_info *ty, int flags)
of the underlying C struct or C++ object. If so then we
need to reset the destructor since the Ruby object no
longer owns the underlying C++ object.*/
if (own) *own = RDATA(obj)->dfree;
if (flags & SWIG_POINTER_DISOWN) {
if (flags & SWIG_TRACK_OBJECTS) {
/* We are tracking objects. Thus we change the destructor

View file

@ -82,7 +82,25 @@
if (ores == SWIG_NEWOBJ) %delete(optr);
}
%typemap(directorout,noblock=1,fragment=frag,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) const Type& {
%typemap(directorout,noblock=1,fragment=frag,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) Type* {
Type *optr = 0;
int ores = asptr_meth($input, &optr);
if (!ores) {
%dirout_fail(SWIG_TypeError,"$type");
}
$result = optr;
if (ores == SWIG_NEWOBJ) {
swig_acquire_ownership(optr);
}
}
%typemap(directorfree,noblock=1) Type*
{
if (director) {
director->swig_release_ownership(%as_voidptr($input));
}
}
%typemap(directorout,noblock=1,fragment=frag,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) Type& {
Type *optr = 0;
int ores = asptr_meth($input, &optr);
if (!ores) {
@ -92,15 +110,18 @@
%dirout_nullref("$type");
}
}
$result = optr;
if (ores == SWIG_NEWOBJ) {
/* Possible thread/reentrant problem here! */
static $*ltype temp = *optr;
$result = &temp;
%delete(optr);
} else {
$result = optr;
swig_acquire_ownership(optr);
}
}
%typemap(directorfree,noblock=1) Type&
{
if (director) {
director->swig_release_ownership(%as_voidptr($input));
}
}
%typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type

View file

@ -29,7 +29,7 @@
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtr)
Char * (Char *buf = 0, int alloc = 0),
const Char * (Char *buf = 0, int alloc = SWIG_OLDOBJ) {
const Char * (Char *buf = 0, int alloc = 0) {
if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum);
}
@ -157,21 +157,41 @@
/* directorout */
%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr)
Char * (Char* buf = 0, int alloc = 0) {
%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
Char * (Char* buf = 0, int alloc = SWIG_NEWOBJ) {
if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) {
%dirout_fail(SWIG_TypeError, "$type");
}
if (alloc == SWIG_NEWOBJ) {
swig_acquire_ownership_array(buf);
}
$result = buf;
}
%typemap(directorfree,noblock=1) Char *
{
if (director) {
director->swig_release_ownership(%as_voidptr($input));
}
}
%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr)
Char * const& (Char* buf = 0, int alloc = 0),
Char const* const& (Char* buf = 0, int alloc = 0) {
%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
Char * const& (Char* buf = 0, int alloc = SWIG_NEWOBJ),
Char const* const& (Char* buf = 0, int alloc = SWIG_NEWOBJ) {
if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) {
%dirout_fail(SWIG_TypeError, "$type");
}
$result = ($1_ltype) &buf;
static $*ltype tmp = buf;
$result = &tmp;
if (alloc == SWIG_NEWOBJ) {
swig_acquire_ownership_array(buf);
}
}
%typemap(directorfree,noblock=1)
Char * const&, Char const* const& {
if (director) {
director->swig_release_ownership(%as_voidptr(*$input));
}
}
#endif /* SWIG_DIRECTOR_TYPEMAPS */
@ -373,7 +393,7 @@
/* Here len doesn't include the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = 0),
(const Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ)
(const Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = 0)
{
if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum);
@ -392,7 +412,7 @@
/* Here size includes the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = 0),
(const Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ)
(const Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = 0)
{
if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum);
@ -413,7 +433,7 @@
/* Here len doesn't include the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(size_t LENGTH, Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0),
(size_t LENGHT, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ)
(size_t LENGHT, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0)
{
if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum);
@ -431,7 +451,7 @@
/* Here size includes the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(size_t SIZE, Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0),
(size_t SIZE, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ)
(size_t SIZE, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0)
{
if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError, "$type",$argnum);

View file

@ -272,19 +272,35 @@
}
$result = *(%reinterpret_cast(argp, $&ltype));
}
%typemap(directorout,noblock=1) SWIGTYPE *(void *argp), SWIGTYPE [](void *argp) {
if (SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags) != SWIG_OK) {
%typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
SWIGTYPE *(void *argp, swig_owntype own), SWIGTYPE [](void *argp, swig_owntype own) {
if (SWIG_ConvertPtrAndOwn($input, &argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own) != SWIG_OK) {
%dirout_fail(SWIG_TypeError,"$type");
}
$result = %reinterpret_cast(argp, $ltype);
swig_acquire_ownership_obj(%as_voidptr($result), own);
}
%typemap(directorout,noblock=1) SWIGTYPE &(void *argp) {
if (SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags) != SWIG_OK) {
%typemap(directorfree,noblock=1) SWIGTYPE *, SWIGTYPE [] {
if (director) {
SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input)));
}
}
%typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
SWIGTYPE &(void *argp, swig_owntype own) {
if (SWIG_ConvertPtrAndOwn($input, &argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own) != SWIG_OK) {
%dirout_fail(SWIG_TypeError,"$type");
}
if (!argp) { %dirout_nullref("$type"); }
$result = %reinterpret_cast(argp, $ltype);
swig_acquire_ownership_obj(%as_voidptr($result), own);
}
%typemap(directorfree,noblock=1) SWIGTYPE & {
if (director) {
SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input)));
}
}
#endif /* SWIG_DIRECTOR_TYPEMAPS */

View file

@ -129,8 +129,14 @@
if (res != SWIG_OK) {
%dirout_fail(res, "$type");
}
static $basetype temp = %static_cast(val, $basetype);
$result = &temp;
$basetype *temp = new $basetype(($basetype)val);
swig_acquire_ownership(temp);
$result = temp;
}
%typemap(directorfree,noblock=1) const Type & {
if (director) {
director->swig_release_ownership(%as_voidptr($input));
}
}
%typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type
%enddef

View file

@ -64,10 +64,11 @@
$result = %reinterpret_cast(argp, $ltype);
}
%typemap(directorout,noblock=1) void * const& ($*ltype temp) {
if (SWIG_ConvertPtr($input, %as_voidptrptr(&temp), 0, $disown) != SWIG_OK) {
%typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) void * const& (void *argp) {
if (SWIG_ConvertPtr($input, &argp, 0, $disown) != SWIG_OK) {
%dirout_fail(SWIG_TypeError,"$type");
}
static $*ltype temp = %reinterpret_cast(argp, $*ltype);
$result = &temp;
}

View file

@ -19,7 +19,6 @@ char cvsroot_python_cxx[] = "$Header$";
#define PYSHADOW_MEMBER 0x2
static String *const_code = 0;
static String *shadow_methods = 0;
static String *module = 0;
static String *package = 0;
static String *mainmodule = 0;
@ -27,6 +26,7 @@ static String *interface = 0;
static String *global_name = 0;
static int shadow = 1;
static int use_kw = 0;
static int director_method_index = 0;
static File *f_runtime = 0;
static File *f_runtime_h = 0;
@ -276,7 +276,6 @@ public:
Swig_register_filebyname("director_h",f_directors_h);
const_code = NewString("");
shadow_methods = NewString("");
methods = NewString("");
Swig_banner(f_runtime);
@ -1153,7 +1152,7 @@ public:
String *iname = Getattr(n,"sym:name");
SwigType *d = Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
Node *parent = Getattr(n,"parentNode");
int director_method = 0;
Parm *p;
int i;
@ -1436,9 +1435,10 @@ public:
if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) {
director_method = 1;
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
if (dirprot_mode() && !is_public(n)) {
if (dirprot_mode() && !is_public(n)) {
Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
Printf(f->code, "PyErr_SetString(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
Printf(f->code, "SWIG_fail;\n");
@ -1461,14 +1461,14 @@ public:
*/
/* Emit the function call */
if (directorsEnabled()) {
if (director_method) {
Printf(f->code, "try {\n");
Printf(f->code, " Swig::UnknownExceptionHandler dh;\n");
}
emit_action(n,f);
if (directorsEnabled()) {
if (director_method) {
Printf(f->code, "} catch (Swig::DirectorException&) {\n");
Printf(f->code, " SWIG_fail;\n");
Printf(f->code, "}\n");
@ -1497,6 +1497,7 @@ public:
/* New addition to unwrap director return values so that the original
* python object is returned instead.
*/
#if 1
int unwrap = 0;
String *decl = Getattr(n, "decl");
int is_pointer = SwigType_ispointer_return(decl);
@ -1505,15 +1506,16 @@ public:
String *type = Getattr(n, "type");
//Node *classNode = Swig_methodclass(n);
//Node *module = Getattr(classNode, "module");
Node *parent = Getattr(n,"parentNode");
Node *module = Getattr(parent, "module");
Node *target = Swig_directormap(module, type);
if (target) unwrap = 1;
}
if (unwrap) {
Wrapper_add_local(f, "resultdirector", "Swig::Director *resultdirector = 0");
Printf(f->code, "resultdirector = SWIG_DIRECTOR_CAST(result);\n");
Printf(f->code, "if (resultdirector) {\n");
Printf(f->code, " resultobj = resultdirector->swig_get_self();\n");
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = SWIG_DIRECTOR_CAST(result);\n");
Printf(f->code, "if (director) {\n");
Printf(f->code, " resultobj = director->swig_get_self();\n");
Printf(f->code, " Py_INCREF(resultobj);\n");
Printf(f->code, "} else {\n");
Printf(f->code,"%s\n", tm);
@ -1521,6 +1523,9 @@ public:
} else {
Printf(f->code,"%s\n", tm);
}
#else
Printf(f->code,"%s\n", tm);
#endif
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to use return type %s in function %s.\n", SwigType_str(d,0), name);
@ -1549,6 +1554,15 @@ public:
Printf(f->code,"%s\n",tm);
}
if (director_method) {
if ((tm = Swig_typemap_lookup_new("directorfree",n,"result",0))) {
Replaceall(tm,"$input","result");
Replaceall(tm,"$result","resultobj");
Printf(f->code,"%s\n",tm);
}
}
Printf(f->code," return resultobj;\n");
/* Error handling code */
@ -1815,6 +1829,8 @@ public:
* ** Moved down due to gcc-2.96 internal error **
* --------------------------------------------------------------- */
int classDirectorMethods(Node *n);
int classDirectorMethod(Node *n, Node *parent, String *super);
/* ------------------------------------------------------------
@ -1934,10 +1950,27 @@ public:
Printf(f_directors_h," mutable std::map<std::string, bool> inner;\n");
}
Printf(f_directors_h,"\n\n");
Printf(f_directors_h,"/* VTable implementation */\n");
Printf(f_directors_h,"public:\n");
Printf(f_directors_h," PyObject *swig_get_method(size_t method_index, const char *method_name) const {\n");
Printf(f_directors_h," PyObject *method = vtable[method_index];\n");
Printf(f_directors_h," if (!method) {\n");
Printf(f_directors_h," swig::PyObject_var name = PyString_FromString(method_name);\n");
Printf(f_directors_h," vtable[method_index] = method = PyObject_GetAttr(swig_get_self(), name);\n");
Printf(f_directors_h," Py_DECREF(swig_get_self());\n");
Printf(f_directors_h," };\n");
Printf(f_directors_h," return method;\n");
Printf(f_directors_h," }\n\n");
Printf(f_directors_h,"private:\n");
Printf(f_directors_h," mutable swig::PyObject_var vtable[%d];\n", director_method_index);
Printf(f_directors_h, "};\n\n");
return Language::classDirectorEnd(n);
}
/* ------------------------------------------------------------
* classDirectorDisown()
* ------------------------------------------------------------ */
@ -2614,7 +2647,7 @@ public:
virtual String *defaultExternalRuntimeFilename() {
return NewString("swigpyrun.h");
}
};
/* ---------------------------------------------------------------
@ -2625,6 +2658,11 @@ public:
*
* ** Moved it here due to internal error on gcc-2.96 **
* --------------------------------------------------------------- */
int PYTHON::classDirectorMethods(Node *n) {
director_method_index = 0;
return Language::classDirectorMethods(n);
}
int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
int is_void = 0;
@ -2856,9 +2894,8 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
/* add the method name as a PyString */
String *pyname = Getattr(n,"sym:name");
String *tmp = NewStringf("static swig::PyObject_var swig_method_name = PyString_FromString(\"%s\")",pyname);
Wrapper_add_local(w, "swig_method_name", tmp);
Delete(tmp);
Wrapper_add_localv(w, "swig_method_index", "const size_t swig_method_index =", NewStringf("%d", director_method_index++), NIL);
Wrapper_add_localv(w, "swig_method_name", "const char * const swig_method_name =", NewStringf("\"%s\"",pyname), NIL);
/* declare method return value
* if the return value is a reference or const reference, a specialized typemap must
@ -2889,14 +2926,16 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
/* pass the method call on to the Python object */
if (dirprot_mode() && !is_public(n))
if (dirprot_mode() && !is_public(n)) {
Printf(w->code, "swig_set_inner(\"%s\", true);\n", name);
}
Printf(w->code, "if (!swig_get_self()) {\n");
Printf(w->code, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname);
Printf(w->code, "}\n");
Wrapper_add_local(w, "method", "swig::PyObject_var method = 0");
Printf(w->code, "method = PyObject_GetAttr(swig_get_self(), swig_method_name);\n");
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, "if (method == NULL) {\n");
Printf(w->code, " Swig::DirectorMethodException::raise(\"Method '%s.%s' doesn't exist\");\n", classname, pyname);
Printf(w->code, "}\n");

View file

@ -1082,7 +1082,7 @@ public:
String *symname = Copy(Getattr(n,"sym:name"));
SwigType *t = Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
Node *parent = Getattr(n,"parentNode");
int director_method = 0;
String *tm;
int need_result = 0;
@ -1220,6 +1220,7 @@ public:
if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) {
director_method = 1;
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
Printf(f->code, "if (director && (director->swig_get_self() == self)) director->swig_set_up();\n");
@ -1244,7 +1245,20 @@ public:
}
}
}
/* Emit the function call */
if (director_method) {
Printf(f->code, "try {\n");
Printf(f->code, " Swig::UnknownExceptionHandler dh;\n");
}
emit_action(n,f);
if (director_method) {
Printf(f->code, "} catch (Swig::DirectorException&) {\n");
Printf(f->code, " SWIG_fail;\n");
Printf(f->code, "}\n");
}
}
/* Return value if necessary */
@ -1270,7 +1284,7 @@ public:
Replaceall(tm, "$track","0");
}
#if 1
// FIXME: this will not try to unwrap directors returned as non-director
// base class pointers!
@ -1283,21 +1297,26 @@ public:
int is_reference = SwigType_isreference_return(decl);
if (is_pointer || is_reference) {
String *type = Getattr(n, "type");
Node *parent = Getattr(n,"parentNode");
Node *modname = Getattr(parent, "module");
Node *target = Swig_directormap(modname, type);
if (target) unwrap = true;
}
if (unwrap) {
Wrapper_add_local(f, "resultdirector", "Swig::Director *resultdirector = 0");
Printf(f->code, "resultdirector = dynamic_cast<Swig::Director *>(result);\n");
Printf(f->code, "if (resultdirector) {\n");
Printf(f->code, " vresult = resultdirector->swig_get_self();\n");
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(result);\n");
Printf(f->code, "if (director) {\n");
Printf(f->code, " vresult = director->swig_get_self();\n");
Printf(f->code, "} else {\n");
Printf(f->code,"%s\n", tm);
Printf(f->code, "}\n");
director_method = 0;
} else {
Printf(f->code,"%s\n", tm);
}
#else
Printf(f->code,"%s\n", tm);
#endif
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to use return type %s.\n", SwigType_str(t,0));
@ -1343,6 +1362,15 @@ public:
Printv(f->code,tm, NIL);
}
if (director_method) {
if ((tm = Swig_typemap_lookup_new("directorfree",n,"result",0))) {
Replaceall(tm,"$input","result");
Replaceall(tm,"$result","vresult");
Printf(f->code,"%s\n",tm);
}
}
/* Wrap things up (in a manner of speaking) */
if (need_result) {
if (current == CONSTRUCTOR_ALLOCATE) {
@ -2218,26 +2246,29 @@ public:
if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0))
{
// Declare a global to hold the depth count
Printf(f_directors, "static int %s = 0;\n", depthCountName);
if (!Getattr(n,"sym:nextSibling")) {
Printf(f_directors, "static int %s = 0;\n", depthCountName);
// Function body
Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName);
Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL);
Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL);
Printf(body->code, "%s++;\n", depthCountName, NIL);
Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
Printf(body->code, "%s--;\n", depthCountName, NIL);
Printv(body->code, "return result;\n", NIL);
Printv(body->code, "}", NIL);
// Function body
Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName);
Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL);
Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL);
Printf(body->code, "%s++;\n", depthCountName, NIL);
Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
Printf(body->code, "%s--;\n", depthCountName, NIL);
Printv(body->code, "return result;\n", NIL);
Printv(body->code, "}", NIL);
// Exception handler
Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName);
Replaceall(tm, "$error", "error");
Printf(rescue->code, "if (%s == 1) ", depthCountName);
Printv(rescue->code, Str(tm), "\n", NIL);
Printf(rescue->code, "%s--;\n", depthCountName);
Printv(rescue->code, "rb_exc_raise(error);\n", NIL);
Printv(rescue->code, "}", NIL);
}
// Exception handler
Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName);
Replaceall(tm, "$error", "error");
Printf(rescue->code, "if (%s == 1) ", depthCountName);
Printv(rescue->code, Str(tm), "\n", NIL);
Printf(rescue->code, "%s--;\n", depthCountName);
Printv(rescue->code, "rb_exc_raise(error);\n", NIL);
Printv(rescue->code, "}", NIL);
// Main code
Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL);