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