Hi,
here is the relevant code of my C++ Python class, that encapsulates Python:
void Python::exec(const char *text)
{
run_cmd(text, this->_namespace);
}
void Python::push(const char *name, PyObject *o)
{
namespace_push(this->_namespace, name, o);
Py_DECREF(o);
}
PyObject *Python::pull(const char *name)
{
return namespace_pull(this->_namespace, name);
}
and here is how to use it:
python->push("i", c2py_int(5));
python->exec("i = i*2");
int i = py2c_int(python->pull("i"));
_assert(i == 10);
where the namespace_pull/push functions as well as c2py_int and
py2c_int are defined in Cython as:
cdef api void namespace_push(object namespace, const_char_p name, object o):
namespace.update({name: o})
cdef api object namespace_pull(object namespace, const_char_p name):
return namespace.get(name)
cdef api object c2py_int(int i):
return i
cdef api int py2c_int(object i):
return i
Everything works fine. This line is ok too:
python->push("i", c2py_int(5));
because c2py_int(5) increfs the object 5, but push() decrefs it, so
all is fine. This line however is leaking:
int i = py2c_int(python->pull("i"));
because pull("i") increfs "i", but py2c_int() doesn't do anything with
the reference, so nothing decrefs it. What is the best way to fix
this?
Here is one way:
PyObject *tmp = python->pull("i");
int i = py2c_int(tmp);
Py_DECREF(tmp);
But this is super annoying from the user experience, because this is
the code that the user has to write by hand and I want to make this as
easy as possible. Another option is to create a function pull_int():
int Python::pull_int(const char* name)
{
PyObject *tmp = python->pull("i");
int i = py2c_int(tmp);
Py_DECREF(tmp);
return i;
}
and the user would use:
int i = p->pull_int("i");
there would be no leak and it would be very easy to use. However, this
means that I have to manually write C++ methods like pull_int() for
every single of my py2c_* conversion functions, which is annoying too.
Yet another option seems to be to use some macro/function to do the
above, e.g. usage would be something like:
int i = F(py2c_int, p->pull_int("i"));
but this is still too complex from the user perspective. I might
figure out some way to construct the pull_int() methods
semiautomatically using some macros.
What would you suggest me?
Ondrej
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev