referents = [] # list "object descriptor -> python object" freelist = None def store(x): "Store the object 'x' and returns a new object descriptor for it." global freelist p = freelist if p is None: p = len(referents) referents.append(x) else: freelist = referents[p] referents[p] = x return p def discard(p): """Discard (i.e. close) the object descriptor 'p'. Return the original object that was attached to 'p'.""" global freelist x = referents[p] referents[p] = freelist freelist = p return x class Ref(object): """For use in 'with Ref(x) as ob': open an object descriptor and returns it in 'ob', and close it automatically when the 'with' statement finishes.""" def __init__(self, x): self.x = x def __enter__(self): self.p = p = store(self.x) return p def __exit__(self, *args): discard(self.p) def count_pyobj_alive(): result = len(referents) p = freelist while p is not None: assert result > 0 result -= 1 p = referents[p] return result # ------------------------------------------------------------ if __name__ == '__main__': import api ffi = api.PythonFFI() ffi.cdef(""" typedef int pyobj_t; int sum_integers(pyobj_t p_list); pyobj_t sum_objects(pyobj_t p_list, pyobj_t p_initial); """) @ffi.pyexport("int(pyobj_t)") def length(p_list): list = referents[p_list] return len(list) @ffi.pyexport("int(pyobj_t, int)") def getitem(p_list, index): list = referents[p_list] return list[index] @ffi.pyexport("pyobj_t(pyobj_t)") def pyobj_dup(p): return store(referents[p]) @ffi.pyexport("void(pyobj_t)") def pyobj_close(p): discard(p) @ffi.pyexport("pyobj_t(pyobj_t, int)") def pyobj_getitem(p_list, index): list = referents[p_list] return store(list[index]) @ffi.pyexport("pyobj_t(pyobj_t, pyobj_t)") def pyobj_add(p1, p2): return store(referents[p1] + referents[p2]) lib = ffi.verify(""" typedef int pyobj_t; /* an "object descriptor" number */ int sum_integers(pyobj_t p_list) { /* this a demo function written in C, using the API defined above: length() and getitem(). */ int i, result = 0; int count = length(p_list); for (i=0; i