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

Reply via email to