Source

pypy / pypy / module / cpyext / c-api.txt

Full commit
Reference Count
===============

XXX

Borrowed References
===================

XXX

PyStringObject support
======================

The problem
-----------

PyString_AsString() returns a (non-movable) pointer to the underlying
buffer, whereas pypy strings are movable.  C code may temporarily
store this address and use it, as long as it owns a reference to the
PyObject.  There is no "release" function to specify that the pointer
is not needed any more.

Note that the pointer may be used to fill the initial value of
string. This is valid only when the string was just allocated, and is
not used elsewhere.

Proposed solution
-----------------

Our emulation of the PyStringObject contains an additional member: a
pointer to a char buffer; it may be NULL.

- A string allocated by pypy will be converted into a PyStringObject
  with a NULL buffer.  When PyString_AsString() is called, memory is
  allocated (with flavor='raw') and content is copied.

- A string allocated with PyString_FromStringAndSize(NULL, size) will
  allocate a buffer with the specified size, but the reference won't
  be stored in the global map py_objects_r2w; there won't be a
  corresponding object in pypy.  When from_ref() or Py_INCREF() is
  called, the pypy string is created, and added in py_objects_r2w.
  The buffer is then supposed to be immutable.

- _PyString_Resize works only on not-yet-pypy'd strings, and returns a
  similar object.

- PyString_Size don't need to force the object. (in this case, another
  "size" member is needed)

- There could be an (expensive!) check in from_ref() that the buffer
  still corresponds to the pypy gc-managed string.

PySequence_Fast support
======================
There are five functions for fast sequence access offered by the CPython API:

PyObject* PySequence_Fast(PyObject *o, const char *m)

PyObject* PySequence_Fast_GET_ITEM(	PyObject *o, int i)

PyObject** PySequence_Fast_ITEMS(	PyObject *o)

PyObject* PySequence_ITEM(	PyObject *o, int i)

int PySequence_Fast_GET_SIZE(	PyObject *o)

PyPy supports four of these, but does not support PySequence_Fast_ITEMS.
(Various ways to support PySequence_Fast_ITEMS were considered. They all had
two things in common: they would have taken a lot of work, and they would have
resulted in incomplete semantics or in poor performance. We decided that a slow
implementation of PySequence_Fast_ITEMS was not very useful.)