You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
1.6 KiB
63 lines
1.6 KiB
7 months ago
|
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
|