Trouble with ref counts in C extension

Michel Pelletier michel at zope.com
Sun Dec 2 22:27:43 EST 2001


I'm having a bit of a problem with a C extension module.  I have two C
methods, push(o) and pop():

static PyObject *
FiclVM_push(FiclVMObject *self, PyObject *args)
{
  PyObject *ob;
  CELL c;

  if (!PyArg_ParseTuple(args, "O:push", &ob))
    return NULL;
  Py_INCREF(ob);

  c.p = ob;
  vmPush(self->ficl_vm, c);

  Py_INCREF(Py_None);
  return Py_None;
}

/* Pop a Python object off the stack */

static PyObject *
FiclVM_pop(FiclVMObject *self, PyObject *args)
{
  CELL c;
  PyObject *ob;

  if (!PyArg_ParseTuple(args, ":pop"))
    return NULL;
  if (!stackDepth(self->ficl_vm->pStack))
    return NULL; // handle better...

  c = vmPop(self->ficl_vm);

  ob = (PyObject*)(c.p);
  Py_DECREF(ob);
  return ob;
}


'c.p' is a "cell pointer" (self->ficl_vm->pStack being a stack of
"cells").  push(o) pushes a reference to an object on the stack and
pop() pops that reference off and returns it.  The stack does nothing to
the object other than just look at it, so there is no behind the scenes
mutation going on.

The problem here is that it doesn't work except for integers. ;)  Here's
an example:

>>> v = system.vm()
>>> v.push(1)
>>> v.pop()
1
>>> v.push((1,))
>>> v.pop()
<nil>
>>> v.pop()
SystemError: Objects/tupleobject.c:123: bad argument to internal
function
>>>

What happened?  My only theory thatI can come up with is taht the
garbage collector collected the tuple.  I don't see why it would do that
though because push(o) Py_INCREFs o.  It will also work all day long
with integer objects and strings no problem.

Any ideas?

Thanks,

-Michel




More information about the Python-list mailing list