import os import sys import fcntl import hashlib import platform from cffi import FFI def suffix(): if platform.system() == "Darwin": return ".dylib" else: return ".so" def ffi_wrap(name, c_code, c_header, tmpdir="/tmp/ccache", cflags="", libraries=None): if libraries is None: libraries = [] cache = name + "_" + hashlib.sha1(c_code.encode('utf-8')).hexdigest() try: os.mkdir(tmpdir) except OSError: pass fd = os.open(tmpdir, 0) fcntl.flock(fd, fcntl.LOCK_EX) try: sys.path.append(tmpdir) try: mod = __import__(cache) except Exception: print(f"cache miss {cache}") compile_code(cache, c_code, c_header, tmpdir, cflags, libraries) mod = __import__(cache) finally: os.close(fd) return mod.ffi, mod.lib def compile_code(name, c_code, c_header, directory, cflags="", libraries=None): if libraries is None: libraries = [] ffibuilder = FFI() ffibuilder.set_source(name, c_code, source_extension='.cpp', libraries=libraries) ffibuilder.cdef(c_header) os.environ['OPT'] = "-fwrapv -O2 -DNDEBUG -std=c++1z" os.environ['CFLAGS'] = cflags ffibuilder.compile(verbose=True, debug=False, tmpdir=directory) def wrap_compiled(name, directory): sys.path.append(directory) mod = __import__(name) return mod.ffi, mod.lib