def test_not_supported_bitfield_in_result(self): ffi = FFI(backend=self.Backend()) ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };") e = py.test.raises(NotImplementedError, ffi.callback, "struct foo_s foo(void)", lambda: 42) assert str(e.value) == ("<struct foo_s(*)(void)>: " "cannot pass as argument or return value a struct with bit fields")
def test_verify_anonymous_struct_with_star_typedef(): ffi = FFI() ffi.cdef("typedef struct { int a; long b; } *foo_t;") verify(ffi, 'test_verify_anonymous_struct_with_star_typedef', "typedef struct { int a; long b; } *foo_t;") p = ffi.new("foo_t", {'b': 42}) assert p.b == 42
def test_unpack_args(): ffi = FFI() ffi.cdef("void foo0(void); void foo1(int); void foo2(int, int);") lib = verify(ffi, "test_unpack_args", """ void foo0(void) { } void foo1(int x) { } void foo2(int x, int y) { } """) assert 'foo0' in repr(lib.foo0) assert 'foo1' in repr(lib.foo1) assert 'foo2' in repr(lib.foo2) lib.foo0() lib.foo1(42) lib.foo2(43, 44) e1 = py.test.raises(TypeError, lib.foo0, 42) e2 = py.test.raises(TypeError, lib.foo0, 43, 44) e3 = py.test.raises(TypeError, lib.foo1) e4 = py.test.raises(TypeError, lib.foo1, 43, 44) e5 = py.test.raises(TypeError, lib.foo2) e6 = py.test.raises(TypeError, lib.foo2, 42) e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47) assert str(e1.value) == "foo0() takes no arguments (1 given)" assert str(e2.value) == "foo0() takes no arguments (2 given)" assert str(e3.value) == "foo1() takes exactly one argument (0 given)" assert str(e4.value) == "foo1() takes exactly one argument (2 given)" assert str(e5.value) == "foo2() takes exactly 2 arguments (0 given)" assert str(e6.value) == "foo2() takes exactly 2 arguments (1 given)" assert str(e7.value) == "foo2() takes exactly 2 arguments (3 given)"
def netscape_spki_from_b64(b64): """Converts a base64 encoded Netscape SPKI DER to a crypto.NetscapeSPKI. PyOpenSSL does not yet support doing that by itself, so some work around through FFI and "internals-patching" trickery is required to perform this conversion. https://github.com/pyca/pyopenssl/issues/177 tracks the issue upstream. """ if not hasattr(netscape_spki_from_b64, 'NETSCAPE_SPKI_b64_decode'): from cffi import FFI as CFFI from OpenSSL._util import ffi as _sslffi, lib as _ssllib cffi = CFFI() cffi.cdef('void* NETSCAPE_SPKI_b64_decode(const char *str, int len);') lib = cffi.dlopen('libssl.so') def wrapper(b64, lib=lib): if isinstance(b64, str): b64 = b64.encode('ascii') b64_ptr = _sslffi.new('char[]', b64) spki_obj = lib.NETSCAPE_SPKI_b64_decode(b64_ptr, len(b64)) if spki_obj == cffi.NULL: raise ValueError("Invalid SPKI base64") def free(spki_obj, ref=b64_ptr): _ssllib.NETSCAPE_SPKI_free(spki_obj) return _sslffi.gc(spki_obj, free) netscape_spki_from_b64.func = wrapper ret = crypto.NetscapeSPKI() ret._spki = netscape_spki_from_b64.func(b64) return ret
def test_global_var_array(): ffi = FFI() ffi.cdef("int a[100];") lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };') lib.a[42] = 123456 assert lib.a[42] == 123456 assert lib.a[0] == 9999
def test_load_library(self): ffi = FFI() ffi.cdef("double sin(double x);") csrc = '/*hi there %s!3*/\n#include <math.h>\n' % self v = Verifier(ffi, csrc, force_generic_engine=self.generic) library = v.load_library() assert library.sin(12.3) == math.sin(12.3)
def test_void_star_accepts_string(self): ffi = FFI(backend=self.Backend()) ffi.cdef("""int strlen(const void *);""") needs_dlopen_none() lib = ffi.dlopen(None) res = lib.strlen(b"hello") assert res == 5
def build_ffi(include_recovery=False, include_schnorr=False, include_ecdh=False): ffi = FFI() source = "#include <secp256k1.h>" cdefs = definitions if include_recovery: cdefs += definitions_recovery source += "\n#include <secp256k1_recovery.h>" if include_schnorr: cdefs += definitions_schnorr source += "\n#include <secp256k1_schnorr.h>" if include_ecdh: cdefs += definitions_ecdh source += "\n#include <secp256k1_ecdh.h>" incpath = [os.environ['INCLUDE_DIR']] if 'INCLUDE_DIR' in os.environ else None libpath = [os.environ['LIB_DIR']] if 'LIB_DIR' in os.environ else None ffi.set_source( "_libsecp256k1", source, libraries=["secp256k1"], library_dirs=libpath, include_dirs=incpath) ffi.cdef(cdefs) return ffi
def test_bad_size_of_global_2(): ffi = FFI() ffi.cdef("int glob[10];") lib = verify(ffi, "test_bad_size_of_global_2", "int glob[9];") e = py.test.raises(ffi.error, "lib.glob") assert str(e.value) == ("global variable 'glob' should be 40 bytes " "according to the cdef, but is actually 36")
def test_msobox_function_interface_on_ffcn_so_calling_ffcn( temp_mf_so_from_mf_f_file ): """.""" # path to shared library so_path = str(temp_mf_so_from_mf_f_file) # print "so_path: ", so_path # load shared library as module module = import_shared_library(so_path) # initialize foreign function interface for library header = """ void ffcn_(double *f, double *t, double *x, double *p, double *u); void ffcn_d_xpu_v_( double *f, double *f_d, double *t, double *x, double *x_d, double *p, double *p_d, double *u, double *u_d, int *nbdirs ); """ # open shared library ffi = FFI() ffi.cdef(header) module = ffi.dlopen(so_path) # function declaration and dimensions func = { "type": "ffcn", "name": "ffcn", "args": ["f", "t", "x", "p", "u"], "deriv": [] } dims = {"f": 5, "t": 1, "x": 5, "p": 5, "u": 4} # create function ffcn = Function(module, dims, func, ffi=ffi, verbose=False) # define input values t = numpy.random.random(dims["t"]) x = numpy.random.random(dims["x"]) p = numpy.random.random(dims["p"]) u = numpy.random.random(dims["u"]) # define output variables desired = numpy.zeros(dims["f"]) actual = numpy.zeros(dims["f"]) # call functions ffcn(actual, t, x, p, u) ffcn_py(desired, t, x, p, u) # compare values print "" print "actual: ", actual print "desired: ", desired print "error: ", lg.norm(desired - actual) assert_allclose(actual, desired)
def test_missing_function(self): ffi = FFI(backend=self.Backend()) ffi.cdef(""" int nonexistent(); """) m = ffi.dlopen(lib_m) assert not hasattr(m, 'nonexistent')
def _setup_cffi(): class LazyLibrary(object): def __init__(self, ffi, libname): self._ffi = ffi self._libname = libname self._lib = None self._lock = threading.Lock() def __getattr__(self, name): if self._lib is None: with self._lock: if self._lib is None: self._lib = self._ffi.dlopen(self._libname) return getattr(self._lib, name) MODULES = ["libnvpair", "libzfs_core"] ffi = FFI() for module_name in MODULES: module = importlib.import_module("." + module_name, __package__) ffi.cdef(module.CDEF) lib = LazyLibrary(ffi, module.LIBRARY) setattr(module, "ffi", ffi) setattr(module, "lib", lib)
def solve_it(input_data): arr = [(int(n[0]), int(n[1])) for n in [line.split() for line in input_data.split("\n") if line]] nitems = arr[0][0] capacity = arr[0][1] values, weights = zip(*arr[1:]) ffi = FFI() ffi.cdef(""" typedef enum {false, true} bool; typedef struct { bool success; int value; bool *route; } Result; Result run(int *values, int *weights, int nitems, int capacity); """) fpath = "data/ks_4_0" lib = ffi.dlopen("libknap.so") res = lib.run(values, weights, nitems, capacity) out = "%d 1\n" % res.value out += " ".join([str(res.route[i]) for i in range(nitems)]) return out
def test_pipe(): ffi = FFI(backend=FakeBackend()) ffi.cdef("int pipe(int pipefd[2]);") C = ffi.dlopen(None) func = C.pipe assert func.name == 'pipe' assert func.BType == '<func (<pointer to <int>>), <int>, False>'
def test_no_args(): ffi = FFI(backend=FakeBackend()) ffi.cdef(""" int foo(void); """) C = ffi.dlopen(None) assert C.foo.BType == '<func (), <int>, False>'
def test_simple(): ffi = FFI(backend=FakeBackend()) ffi.cdef("double sin(double x);") m = ffi.dlopen(lib_m) func = m.sin # should be a callable on real backends assert func.name == 'sin' assert func.BType == '<func (<double>), <double>, False>'
def test_not_supported_bitfield_in_result(self): ffi = FFI(backend=self.Backend()) ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };") e = py.test.raises(NotImplementedError, ffi.callback, "struct foo_s foo(void)", lambda: 42) assert str(e.value) == ("struct foo_s(*)(): " "callback with unsupported argument or return type or with '...'")
def test_win_common_types(): from cffi.commontypes import COMMON_TYPES, _CACHE from cffi.commontypes import win_common_types, resolve_common_type # def clear_all(extra={}, old_dict=COMMON_TYPES.copy()): COMMON_TYPES.clear() COMMON_TYPES.update(old_dict) COMMON_TYPES.update(extra) _CACHE.clear() # for maxsize in [2 ** 32 - 1, 2 ** 64 - 1]: ct = win_common_types(maxsize) clear_all(ct) for key in sorted(ct): resolve_common_type(key) # assert did not crash # now try to use e.g. WPARAM (-> UINT_PTR -> unsigned 32/64-bit) for maxsize in [2 ** 32 - 1, 2 ** 64 - 1]: ct = win_common_types(maxsize) clear_all(ct) ffi = FFI() value = int(ffi.cast("WPARAM", -1)) assert value == maxsize # clear_all()
def _init_api(): lib_name = ctypes.util.find_library("ssh") if not lib_name: raise exceptions.PystasshException("libssh not found, please visit https://www.libssh.org/get-it/") ffi = FFI() lib = ffi.dlopen(lib_name) ffi.cdef(""" void* ssh_new(); int ssh_options_set(void*, int, char*); int ssh_connect(void*); int ssh_disconnect(void*); int ssh_is_connected(void*); char* ssh_get_error(void*); int ssh_userauth_password(void*, char*, char*); int ssh_userauth_autopubkey(void*, char*); void* ssh_channel_new(void*); int ssh_channel_open_session(void*); int ssh_channel_is_open(void*); void ssh_channel_free(void*); int ssh_channel_request_exec(void*, char*); int ssh_channel_request_pty(void*); int ssh_channel_request_shell(void*); int ssh_channel_get_exit_status(void*); int ssh_channel_read(void*, char*, int, int); int ssh_channel_send_eof(void*); """) return ffi, lib
def test_ffi_new_allocator_4(self): ffi = FFI(backend=self.Backend()) py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None) # def myalloc2(size): raise LookupError alloc2 = ffi.new_allocator(myalloc2) py.test.raises(LookupError, alloc2, "int[5]") # def myalloc3(size): return 42 alloc3 = ffi.new_allocator(myalloc3) e = py.test.raises(TypeError, alloc3, "int[5]") assert str(e.value) == "alloc() must return a cdata object (got int)" # def myalloc4(size): return ffi.cast("int", 42) alloc4 = ffi.new_allocator(myalloc4) e = py.test.raises(TypeError, alloc4, "int[5]") assert str(e.value) == "alloc() must return a cdata pointer, not 'int'" # def myalloc5(size): return ffi.NULL alloc5 = ffi.new_allocator(myalloc5) py.test.raises(MemoryError, alloc5, "int[5]")
def _run_callback_in_thread(): ffi = FFI() ffi.cdef(""" typedef int (*mycallback_func_t)(int, int); int threaded_ballback_test(mycallback_func_t mycb); """) lib = ffi.verify(""" #include <pthread.h> typedef int (*mycallback_func_t)(int, int); void *my_wait_function(void *ptr) { mycallback_func_t cbfunc = (mycallback_func_t)ptr; cbfunc(10, 10); cbfunc(12, 15); return NULL; } int threaded_ballback_test(mycallback_func_t mycb) { pthread_t thread; pthread_create(&thread, NULL, my_wait_function, (void*)mycb); return 0; } """, extra_compile_args=['-pthread']) seen = [] @ffi.callback('int(*)(int,int)') def mycallback(x, y): time.sleep(0.022) seen.append((x, y)) return 0 lib.threaded_ballback_test(mycallback) count = 300 while len(seen) != 2: time.sleep(0.01) count -= 1 assert count > 0, "timeout" assert seen == [(10, 10), (12, 15)]
def load_inline_module(): """ Create an inline module, return the corresponding ffi and dll objects. """ from cffi import FFI # We can't rely on libc availability on Windows anymore, so we use our # own compiled wrappers (see https://bugs.python.org/issue23606). defs = """ double _numba_test_sin(double x); double _numba_test_cos(double x); int foo(int a, int b, int c); """ source = """ static int foo(int a, int b, int c) { return a + b * c; } """ ffi = FFI() ffi.cdef(defs) # Load the _helperlib namespace from numba import _helperlib return ffi, ffi.dlopen(_helperlib.__file__)
class Binding(object): def __init__(self, extra_objects=None, include_dirs=None, libraries=None): self.ffi = FFI() self.ffi.cdef(cdef) self._lib = None if extra_objects is None: extra_objects = [] self._extra_objects = extra_objects if include_dirs is None: include_dirs = [] self._include_dirs = include_dirs if libraries is None: libraries = ["fuzzy"] self._libraries = libraries def verify(self): self._lib = self.ffi.verify( source, ext_package="ssdeep", extra_objects=self._extra_objects, include_dirs=self._include_dirs, modulename=_create_modulename(cdef, source, __version__), libraries=self._libraries, ) @property def lib(self): if self._lib is None: self.verify() return self._lib
def test_vararg(): ffi = FFI(backend=FakeBackend()) ffi.cdef("short foo(int, ...);") C = ffi.dlopen(None) func = C.foo assert func.name == 'foo' assert func.BType == '<func (<int>), <short>, True>'
def test_ffi_new_allocator_2(self): ffi = FFI(backend=self.Backend()) seen = [] def myalloc(size): seen.append(size) return ffi.new("char[]", b"X" * size) def myfree(raw): seen.append(raw) alloc1 = ffi.new_allocator(myalloc, myfree) alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree, should_clear_after_alloc=False) p1 = alloc1("int[10]") p2 = alloc2("int[]", 10) assert seen == [40, 40] assert ffi.typeof(p1) == ffi.typeof("int[10]") assert ffi.sizeof(p1) == 40 assert ffi.typeof(p2) == ffi.typeof("int[]") assert ffi.sizeof(p2) == 40 assert p1[5] == 0 assert p2[6] == ord('X') * 0x01010101 raw1 = ffi.cast("char *", p1) raw2 = ffi.cast("char *", p2) del p1, p2 retries = 0 while len(seen) != 4: retries += 1 assert retries <= 5 import gc; gc.collect() assert seen == [40, 40, raw1, raw2] assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>" assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
def generate_tgl_update(): from cffi import FFI ffi_ = FFI() ffi_.cdef("""int printf(const char *format, ...);""") C = ffi_.dlopen(None) cb = ffi.new('struct tgl_update_callback *') cb.new_msg = _tgl_upd_new_msg_cb cb.marked_read = _tgl_upd_marked_read_cb cb.logprintf = C.printf cb.type_notification = _tgl_upd_type_notification_cb cb.type_in_chat_notification = _tgl_upd_type_in_chat_notification_cb cb.type_in_secret_chat_notification = _tgl_upd_type_in_secret_chat_notification_cb cb.status_notification = _tgl_upd_status_notification_cb cb.user_registered = _tgl_upd_user_registered_cb cb.user_activated = _tgl_upd_user_activated_cb cb.new_authorization = _tgl_upd_new_authorization_cb cb.chat_update = _tgl_upd_chat_update_cb cb.user_update = _tgl_upd_user_update_cb cb.secret_chat_update = _tgl_upd_secret_chat_update_cb cb.msg_receive = _tgl_upd_msg_receive_cb cb.our_id = _tgl_upd_our_id_cb cb.notification = _tgl_upd_notification_cb cb.user_status_update = _tgl_upd_user_status_update_cb #use the default implementation #cb.create_print_name = _tgl_upd_create_print_name_cb return cb
def test_dlopen_flags(self): ffi = FFI(backend=self.Backend()) ffi.cdef(""" double cos(double x); """) m = ffi.dlopen(lib_m, ffi.RTLD_LAZY | ffi.RTLD_LOCAL) x = m.cos(1.23) assert x == math.cos(1.23)
def test_tag(self): ffi = FFI() ffi.cdef("/* %s test_tag */ double test1tag(double x);" % self) csrc = "double test1tag(double x) { return x - 42.0; }" lib = ffi.verify(csrc, force_generic_engine=self.generic, tag='xxtest_tagxx') assert lib.test1tag(143) == 101.0 assert '_cffi_xxtest_tagxx_' in ffi.verifier.modulefilename
def loadCffi(libname, cdef_text, libpath): if libname in _ft_cffi: return _ft_cffi[libname] _ffi = FFI() _ffi.cdef(cdef_text) sofile = libpath + "/" + libname + ".so" _lib = _ffi.dlopen(sofile) _ft_cffi[libname] = (_lib, _ffi)
def test_name_from_checksum_of_csrc(self): names = [] for csrc in ['123', '123', '1234']: ffi = FFI() ffi.cdef("double sin(double x);") v = Verifier(ffi, csrc, force_generic_engine=self.generic) names.append(v.get_module_name()) assert names[0] == names[1] != names[2]