[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