[pypy-commit] cffi default: Two demos of how CFFI can be used to write your own C functions

arigo noreply at buildbot.pypy.org
Fri Aug 31 15:21:05 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r906:8c4195c65dac
Date: 2012-08-31 15:20 +0200
http://bitbucket.org/cffi/cffi/changeset/8c4195c65dac/

Log:	Two demos of how CFFI can be used to write your own C functions
	using whatever API is most suitable.

diff --git a/demo/api.py b/demo/api.py
new file mode 100644
--- /dev/null
+++ b/demo/api.py
@@ -0,0 +1,62 @@
+import cffi
+from cffi import FFI
+
+class PythonFFI(FFI):
+
+    def __init__(self, backend=None):
+        FFI.__init__(self, backend=backend)
+        self._pyexports = {}
+
+    def pyexport(self, signature):
+        tp = self._typeof(signature, consider_function_as_funcptr=True)
+        def decorator(func):
+            name = func.__name__
+            if name in self._pyexports:
+                raise cffi.CDefError("duplicate pyexport'ed function %r"
+                                     % (name,))
+            callback_var = self.getctype(tp, name)
+            self.cdef("%s;" % callback_var)
+            self._pyexports[name] = _PyExport(tp, func)
+        return decorator
+
+    def verify(self, source='', **kwargs):
+        extras = []
+        pyexports = sorted(self._pyexports.items())
+        for name, export in pyexports:
+            callback_var = self.getctype(export.tp, name)
+            extras.append("%s;" % callback_var)
+        extras.append(source)
+        source = '\n'.join(extras)
+        lib = FFI.verify(self, source, **kwargs)
+        for name, export in pyexports:
+            cb = self.callback(export.tp, export.func)
+            export.cb = cb
+            setattr(lib, name, cb)
+        return lib
+
+
+class _PyExport(object):
+    def __init__(self, tp, func):
+        self.tp = tp
+        self.func = func
+
+
+if __name__ == '__main__':
+    ffi = PythonFFI()
+
+    @ffi.pyexport("int(int)")
+    def add1(n):
+        print n
+        return n + 1
+
+    ffi.cdef("""
+        int f(int);
+    """)
+
+    lib = ffi.verify("""
+        int f(int x) {
+            return add1(add1(x));
+        }
+    """)
+
+    assert lib.f(5) == 7
diff --git a/demo/pyobj.py b/demo/pyobj.py
new file mode 100644
--- /dev/null
+++ b/demo/pyobj.py
@@ -0,0 +1,58 @@
+import api
+
+ffi = api.PythonFFI()
+
+referents = []
+freelist = None
+
+def store(x):
+    global freelist
+    if freelist is None:
+        i = len(referents)
+        referents.append(x)
+    else:
+        i = freelist = referents[freelist]
+        referents[i] = x
+    return i
+
+def discard(i):
+    global freelist
+    referents[i] = freelist
+    freelist = i
+
+class Ref(object):
+    def __init__(self, x):
+        self.x = x
+    def __enter__(self):
+        self.i = i = store(self.x)
+        return i
+    def __exit__(self, *args):
+        discard(self.i)
+
+# ------------------------------------------------------------
+
+ffi.cdef("""
+    typedef int pyobj_t;
+    int sum(pyobj_t oblist, int count);
+""")
+
+ at ffi.pyexport("int(pyobj_t, int)")
+def getitem(oblist, index):
+    list = referents[oblist]
+    return list[index]
+
+lib = ffi.verify("""
+    typedef int pyobj_t;
+
+    int sum(pyobj_t oblist, int count) {
+        int i, result = 0;
+        for (i=0; i<count; i++) {
+            int n = getitem(oblist, i);
+            result += n;
+        }
+        return result;
+    }
+""")
+
+with Ref([10, 20, 30, 40]) as oblist:
+    print lib.sum(oblist, 4)


More information about the pypy-commit mailing list