[pypy-dev] swig + pypy - object reference counting
Alex Pyattaev
alex.pyattaev at gmail.com
Wed Sep 28 11:41:05 CEST 2011
Well,
the point is that first I make an owned copy of the object:
%typemap(in) void* {
Py_XINCREF($input);
$1 = $input;
}
Here is the storage struct:
struct event{
int code;
void* node_tx;
void* node_rx;
void* packet;
double signal_power;
double noise_power;
double BER;
struct event* next;
};
For the C-code python objects are just void*, so they are perfectly safe.
Now, when I fetch the objects by my own get function i have the following
typemap:
%typemap (out) event_t* {
if ($1 == NULL)
{
$result = Py_None;
Py_XINCREF($result);
}
else
{
$result = PyTuple_New(7);
PyTuple_SetItem($result, 0 , PyInt_FromLong($1->code));
PyTuple_SetItem($result, 1 , $1->node_tx);
PyTuple_SetItem($result, 2 , $1->node_rx);
PyTuple_SetItem($result, 3 , $1->packet);
#ifdef PYTHON_PYPY
Py_XINCREF($1->node_tx);
Py_XINCREF($1->node_rx);
Py_XINCREF($1->packet);
#endif
PyTuple_SetItem($result, 4 , PyFloat_FromDouble($1->signal_power));
PyTuple_SetItem($result, 5 , PyFloat_FromDouble($1->noise_power));
PyTuple_SetItem($result, 6 , PyFloat_FromDouble($1->BER));
free($1);
Py_XINCREF($result);
}
}
As you can see, in Python I do not need to INCREF object references, but in
PYPY I do, otherwise it crashes.
In the wrapper function it looks like this:
SWIGINTERN PyObject *_wrap_fetch_event(PyObject *SWIGUNUSEDPARM(self),
PyObject *args) {
PyObject *resultobj = 0;
event_t *result = 0 ;
if (!SWIG_Python_UnpackTuple(args,"fetch_event",0,0,0)) SWIG_fail;
result = (event_t *)fetch_event();
{
if (result == NULL)
{
resultobj = Py_None;
Py_XINCREF(resultobj);
}
else
{
resultobj = PyTuple_New(7);
#ifdef PYTHON_PYPY
Py_XINCREF($1->node_tx);
Py_XINCREF($1->node_rx);
Py_XINCREF($1->packet);
#endif
PyTuple_SetItem(resultobj, 0 , PyInt_FromLong(result->code));
PyTuple_SetItem(resultobj, 1 , result->node_tx);
PyTuple_SetItem(resultobj, 2 , result->node_rx);
PyTuple_SetItem(resultobj, 3 , result->packet);
PyTuple_SetItem(resultobj, 4 , PyFloat_FromDouble(result-
>signal_power));
PyTuple_SetItem(resultobj, 5 , PyFloat_FromDouble(result->noise_power));
PyTuple_SetItem(resultobj, 6 , PyFloat_FromDouble(result->BER));
free(result);
Py_XINCREF(resultobj);
}
}
return resultobj;
fail:
return NULL;
}
So essentially the same code works in different ways for python and pypy. IMHO
there is a bug somewhere, but I have not time ATM to find it. And yes, it
leaks memory like hell due to extra ref=(
On Wednesday 28 September 2011 11:11:07 Amaury Forgeot d'Arc wrote:
> 2011/9/28 Alex Pyattaev <alex.pyattaev at gmail.com>
>
> > Hi!
> > I have a quite sophisticated program that can be summarized as follows:
> > 1. Save a pypy object pointer inside C program. Here I call Py_XINCREF
> > so
> > that
> > it does not get deleted.
> > 2. Do some logic, move this reference around C code.
> > 3. Return a python tuple via typemap, here I am probably supposed to
> > return a
> > borrowed reference. And in Python2 it works just fine. BUT. In pypy, for
> > some
> > reason, it causes segfault with following message:
> > """
> > Fatal error in cpyext, CPython compatibility layer, calling
> > PyTuple_SetItem Either report a bug or consider not using this
> > particular extension <InvalidPointerException object at 0x14a87a8>
> >
> > RPython traceback:
> > File "module_cpyext_api_1.c", line 28965, in PyTuple_SetItem
> > File "module_cpyext_pyobject.c", line 1018, in CpyTypedescr_realize
> >
> > Segmentation fault
> > """
> > If I call Py_XINCREF before returning the object, the crash does not
> > happen and the memory does not seem to be leaking (at least not
> > noticeably massive amounts of it). So it seems that PyPy is somewhat
> > incompatible with Python2 in
> > that matter.
> > If you want I could send the code example that triggers the bug (it IS
> > quite
> > large app, which might have many more bugs apart from this, but still).
>
> Isn't PyTuple_SetItem supposed to "steal" the reference?
> In this case you'd better INCREF the object if it is globally shared.
More information about the pypy-dev
mailing list