This patch creates a new C type, py_object_incref, for use as a return type for pythonapi functions that borrow a reference and as an argument for functions that steal a reference. py_object_incref cannot be instantiated or used as a structure field. As side benefits a CDataType subclass now accepts an optional _flags_ attribute to set selected stgdict flag fields and a new flag is defined to prevent a C type from being a structure field.
The patch is applied to ctypes 1.0.1 release. It alters files _ctypes.c, ctypes.h, cfield.c, stgdict.c,__init__.py . The patch includes a new unit test test_py_object_incref.py . The following invocation of GNU patch 2.5 from the directory containing ctypes-1.0.1 seems to work:
patch -p0 <py_object_incref.diff
The patch has only been tested with MSVC 6 and Python 2.3. The following Python session is a usage example.
Python 2.3.5 (#62, Feb 8 2005, 16:23:02) [MSC v.1200 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> py_object_incref._type_
'o'
>>> py_object_incref._flags_
256
>>> # Borrowed reference
...
>>> PyList_GetItem = pythonapi.PyList_GetItem
>>> PyList_GetItem.restype = py_object_incref
>>> PyList_GetItem.argtypes = [py_object, c_int]
>>> PyList_GetItem([1, 2, 3], 1)
2
>>> # Stolen reference
...
>>> PyList_SetItem = pythonapi.PyList_SetItem
>>> PyList_SetItem.argtypes = [py_object, c_int, py_object_incref]
>>> x = [1, 2, 3]
>>> PyList_SetItem(x, 2, 5)
0
>>> x
[1, 2, 5]
>>> # py_object_incref instances and fields not allowed
...
>>> py_object_incref(None)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "C:\prg\ctypes-1.0.1\ctypes\__init__.py", line 148, in __new__
_type_ = "H"
NotImplementedError: py_object_incref for argument and return types only.
>>> class S(Structure):
... _fields_ = ('o', py_object_incref),
...
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: field 0 must be an allowed C type: got py_object_incref instead
multi-patch file for ctypes-1.0.1