Source

cffi / demo / pyobj.py

Diff from to

File demo/pyobj.py

-import api
-
-ffi = api.PythonFFI()
 
 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)
+    p = freelist
+    if p is None:
+        p = len(referents)
         referents.append(x)
     else:
-        i = freelist
-        freelist = referents[freelist]
-        referents[i] = x
-    return i
+        freelist = referents[p]
+        referents[p] = x
+    return p
 
-def discard(i):
-    "Discard (i.e. close) the object descriptor 'i'."
+def discard(p):
+    """Discard (i.e. close) the object descriptor 'p'.
+    Return the original object that was attached to 'p'."""
     global freelist
-    referents[i] = freelist
-    freelist = i
+    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
     def __init__(self, x):
         self.x = x
     def __enter__(self):
-        self.i = i = store(self.x)
-        return i
+        self.p = p = store(self.x)
+        return p
     def __exit__(self, *args):
-        discard(self.i)
+        discard(self.p)
 
 def count_pyobj_alive():
     result = len(referents)
-    i = freelist
-    while i is not None:
+    p = freelist
+    while p is not None:
         assert result > 0
         result -= 1
-        i = referents[i]
+        p = referents[p]
     return result
 
 # ------------------------------------------------------------
 
-ffi.cdef("""
-    typedef int pyobj_t;
-    int sum_integers(pyobj_t oblist);
-    pyobj_t sum_objects(pyobj_t oblist, pyobj_t obinitial);
-""")
+if __name__ == '__main__':
+    import api
 
-@ffi.pyexport("int(pyobj_t)")
-def length(oblist):
-    list = referents[oblist]
-    return len(list)
+    ffi = api.PythonFFI()
 
-@ffi.pyexport("int(pyobj_t, int)")
-def getitem(oblist, index):
-    list = referents[oblist]
-    return list[index]
+    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("pyobj_t(pyobj_t)")
-def pyobj_dup(ob):
-    return store(referents[ob])
+    @ffi.pyexport("int(pyobj_t)")
+    def length(p_list):
+        list = referents[p_list]
+        return len(list)
 
-@ffi.pyexport("void(pyobj_t)")
-def pyobj_close(ob):
-    discard(ob)
+    @ffi.pyexport("int(pyobj_t, int)")
+    def getitem(p_list, index):
+        list = referents[p_list]
+        return list[index]
 
-@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)")
+    def pyobj_dup(p):
+        return store(referents[p])
 
-@ffi.pyexport("pyobj_t(pyobj_t, pyobj_t)")
-def pyobj_add(ob1, ob2):
-    return store(referents[ob1] + referents[ob2])
+    @ffi.pyexport("void(pyobj_t)")
+    def pyobj_close(p):
+        discard(p)
 
-lib = ffi.verify("""
-    typedef int pyobj_t;    /* an "object descriptor" number */
+    @ffi.pyexport("pyobj_t(pyobj_t, int)")
+    def pyobj_getitem(p_list, index):
+        list = referents[p_list]
+        return store(list[index])
 
-    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++) {
-            int n = getitem(oblist, i);
-            result += n;
+    @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<count; i++) {
+                int n = getitem(p_list, i);
+                result += n;
+            }
+            return result;
         }
-        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;
+        pyobj_t sum_objects(pyobj_t p_list, pyobj_t p_initial) {
+            /* same as above, but keeps all additions as Python objects */
+            int i;
+            int count = length(p_list);
+            pyobj_t p1 = pyobj_dup(p_initial);
+            for (i=0; i<count; i++) {
+                pyobj_t p2 = pyobj_getitem(p_list, i);
+                pyobj_t p3 = pyobj_add(p1, p2);
+                pyobj_close(p2);
+                pyobj_close(p1);
+                p1 = p3;
+            }
+            return p1;
         }
-        return ob;
-    }
-""")
+    """)
 
-with Ref([10, 20, 30, 40]) as oblist:
-    print lib.sum_integers(oblist)
-    with Ref(0) as obinitial:
-        obresult = lib.sum_objects(oblist, obinitial)
-        print referents[obresult]
-        discard(obresult)
+    with Ref([10, 20, 30, 40]) as p_list:
+        print lib.sum_integers(p_list)
+        with Ref(5) as p_initial:
+            result = discard(lib.sum_objects(p_list, p_initial))
+            print result
 
-assert not count_pyobj_alive()
+    assert count_pyobj_alive() == 0