diff options
author | Armin Rigo <arigo@tunes.org> | 2012-08-31 15:40:53 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2012-08-31 15:40:53 +0200 |
commit | 3fcda41f21dd0058888e876ee9e895f7cc47f6f6 (patch) | |
tree | e83c49d78d1cabe2e6df0ee681eb45d57b54cef9 /demo | |
parent | d0c0983ee4edbf24487858f620d7b63444817157 (diff) | |
download | cffi-3fcda41f21dd0058888e876ee9e895f7cc47f6f6.tar.gz |
Complete the example.
Diffstat (limited to 'demo')
-rw-r--r-- | demo/pyobj.py | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/demo/pyobj.py b/demo/pyobj.py index 29be622..9bfb3a4 100644 --- a/demo/pyobj.py +++ b/demo/pyobj.py @@ -2,25 +2,31 @@ import api ffi = api.PythonFFI() -referents = [] +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 if freelist is None: i = len(referents) referents.append(x) else: - i = freelist = referents[freelist] + i = freelist + freelist = referents[freelist] referents[i] = x return i def discard(i): + "Discard (i.e. close) the object descriptor 'i'." global freelist referents[i] = freelist freelist = i 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): @@ -29,11 +35,21 @@ class Ref(object): def __exit__(self, *args): discard(self.i) +def count_pyobj_alive(): + result = len(referents) + i = freelist + while i is not None: + assert result > 0 + result -= 1 + i = referents[i] + return result + # ------------------------------------------------------------ ffi.cdef(""" typedef int pyobj_t; - int sum(pyobj_t oblist); + int sum_integers(pyobj_t oblist); + pyobj_t sum_objects(pyobj_t oblist, pyobj_t obinitial); """) @ffi.pyexport("int(pyobj_t)") @@ -46,10 +62,29 @@ def getitem(oblist, index): list = referents[oblist] return list[index] +@ffi.pyexport("pyobj_t(pyobj_t)") +def pyobj_dup(ob): + return store(referents[ob]) + +@ffi.pyexport("void(pyobj_t)") +def pyobj_close(ob): + discard(ob) + +@ffi.pyexport("pyobj_t(pyobj_t, int)") +def pyobj_getitem(oblist, index): + list = referents[oblist] + return store(list[index]) + +@ffi.pyexport("pyobj_t(pyobj_t, pyobj_t)") +def pyobj_add(ob1, ob2): + return store(referents[ob1] + referents[ob2]) + lib = ffi.verify(""" - typedef int pyobj_t; + typedef int pyobj_t; /* an "object descriptor" number */ - int sum(pyobj_t oblist) { + int sum_integers(pyobj_t oblist) { + /* this a demo function written in C, using the API + defined above: length() and getitem(). */ int i, result = 0; int count = length(oblist); for (i=0; i<count; i++) { @@ -58,7 +93,28 @@ lib = ffi.verify(""" } return result; } + + pyobj_t sum_objects(pyobj_t oblist, pyobj_t obinitial) { + /* same as above, but keeps all additions as Python objects */ + int i; + int count = length(oblist); + pyobj_t ob = pyobj_dup(obinitial); + for (i=0; i<count; i++) { + pyobj_t ob2 = pyobj_getitem(oblist, i); + pyobj_t ob3 = pyobj_add(ob, ob2); + pyobj_close(ob2); + pyobj_close(ob); + ob = ob3; + } + return ob; + } """) with Ref([10, 20, 30, 40]) as oblist: - print lib.sum(oblist) + print lib.sum_integers(oblist) + with Ref(0) as obinitial: + obresult = lib.sum_objects(oblist, obinitial) + print referents[obresult] + discard(obresult) + +assert not count_pyobj_alive() |