def test_some_integer_type(): ffi = FFI() ffi.cdef(""" typedef int... foo_t; typedef unsigned long... bar_t; typedef struct { foo_t a, b; } mystruct_t; foo_t foobar(bar_t, mystruct_t); static const bar_t mu = -20; static const foo_t nu = 20; """) lib = verify(ffi, 'test_some_integer_type', """ typedef unsigned long long foo_t; typedef short bar_t; typedef struct { foo_t a, b; } mystruct_t; static foo_t foobar(bar_t x, mystruct_t s) { return (foo_t)x + s.a + s.b; } static const bar_t mu = -20; static const foo_t nu = 20; """) assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long") assert ffi.sizeof("bar_t") == ffi.sizeof("short") maxulonglong = 2 ** 64 - 1 assert int(ffi.cast("foo_t", -1)) == maxulonglong assert int(ffi.cast("bar_t", -1)) == -1 assert lib.foobar(-1, [0, 0]) == maxulonglong assert lib.foobar(2 ** 15 - 1, [0, 0]) == 2 ** 15 - 1 assert lib.foobar(10, [20, 31]) == 61 assert lib.foobar(0, [0, maxulonglong]) == maxulonglong py.test.raises(OverflowError, lib.foobar, 2 ** 15, [0, 0]) py.test.raises(OverflowError, lib.foobar, -(2 ** 15) - 1, [0, 0]) py.test.raises(OverflowError, ffi.new, "mystruct_t *", [0, -1]) assert lib.mu == -20 assert lib.nu == 20
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 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 test_some_integer_type(): ffi = FFI() ffi.cdef(""" typedef int... foo_t; typedef unsigned long... bar_t; typedef struct { foo_t a, b; } mystruct_t; foo_t foobar(bar_t, mystruct_t); static const bar_t mu = -20; static const foo_t nu = 20; """) lib = verify( ffi, 'test_some_integer_type', """ typedef unsigned long long foo_t; typedef short bar_t; typedef struct { foo_t a, b; } mystruct_t; static foo_t foobar(bar_t x, mystruct_t s) { return (foo_t)x + s.a + s.b; } static const bar_t mu = -20; static const foo_t nu = 20; """) assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long") assert ffi.sizeof("bar_t") == ffi.sizeof("short") maxulonglong = 2**64 - 1 assert int(ffi.cast("foo_t", -1)) == maxulonglong assert int(ffi.cast("bar_t", -1)) == -1 assert lib.foobar(-1, [0, 0]) == maxulonglong assert lib.foobar(2**15 - 1, [0, 0]) == 2**15 - 1 assert lib.foobar(10, [20, 31]) == 61 assert lib.foobar(0, [0, maxulonglong]) == maxulonglong py.test.raises(OverflowError, lib.foobar, 2**15, [0, 0]) py.test.raises(OverflowError, lib.foobar, -(2**15) - 1, [0, 0]) py.test.raises(OverflowError, ffi.new, "mystruct_t *", [0, -1]) assert lib.mu == -20 assert lib.nu == 20
def test_struct_array_guess_length_3(): ffi = FFI() ffi.cdef("struct foo_s { int a[][...]; };") lib = verify(ffi, 'test_struct_array_guess_length_3', "struct foo_s { int x; int a[5][7]; int y; };") assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int') s = ffi.new("struct foo_s *") assert ffi.typeof(s.a) == ffi.typeof("int(*)[7]") assert s.a[4][6] == 0 py.test.raises(IndexError, 's.a[4][7]') assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
def test_struct_array_guess_length_3(): ffi = FFI() ffi.cdef("struct foo_s { int a[][...]; };") lib = verify(ffi, 'test_struct_array_guess_length_3', "struct foo_s { int x; int a[5][7]; int y; };") assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int') s = ffi.new("struct foo_s *") assert ffi.typeof(s.a) == ffi.typeof("int(*)[7]") assert s.a[4][6] == 0 py.test.raises(IndexError, 's.a[4][7]') assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
def test_some_float_invalid_3(): ffi = FFI() ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);") lib = verify(ffi, 'test_some_float_invalid_3', """ typedef long double foo_t; foo_t neg(foo_t x) { return -x; } """) if ffi.sizeof("long double") == ffi.sizeof("double"): assert lib.neg(12.3) == -12.3 else: e = py.test.raises(ffi.error, getattr, lib, 'neg') assert str(e.value) == ("primitive floating-point type is " "'long double', not supported for now with " "the syntax 'typedef double... xxx;'")
def test_verify_anonymous_enum_with_typedef(): ffi = FFI() ffi.cdef("typedef enum { AA, ... } e1;") lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef1', "typedef enum { BB, CC, AA } e1;") assert lib.AA == 2 assert ffi.sizeof("e1") == ffi.sizeof("int") assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>" # ffi = FFI() ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize) lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2', "typedef enum { AA=%d } e1;" % sys.maxsize) assert lib.AA == sys.maxsize assert ffi.sizeof("e1") == ffi.sizeof("long")
def test_verify_anonymous_enum_with_typedef(): ffi = FFI() ffi.cdef("typedef enum { AA, ... } e1;") lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef1', "typedef enum { BB, CC, AA } e1;") assert lib.AA == 2 assert ffi.sizeof("e1") == ffi.sizeof("int") assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>" # ffi = FFI() ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize) lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2', "typedef enum { AA=%d } e1;" % sys.maxsize) assert lib.AA == sys.maxsize assert ffi.sizeof("e1") == ffi.sizeof("long")
def test_verify_enum(): ffi = FFI() ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""") lib = verify( ffi, 'test_verify_enum', "enum e1 { A1, B1, C1=%d };" % sys.maxsize + "enum e2 { A2, B2, C2 };") ffi.typeof("enum e1") ffi.typeof("enum e2") assert lib.A1 == 0 assert lib.B1 == 1 assert lib.A2 == 0 assert lib.B2 == 1 assert ffi.sizeof("enum e1") == ffi.sizeof("long") assert ffi.sizeof("enum e2") == ffi.sizeof("int") assert repr(ffi.cast("enum e1", 0)) == "<cdata 'enum e1' 0: A1>"
def test_verify_enum(): ffi = FFI() ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""") lib = verify(ffi, 'test_verify_enum', "enum e1 { A1, B1, C1=%d };" % sys.maxsize + "enum e2 { A2, B2, C2 };") ffi.typeof("enum e1") ffi.typeof("enum e2") assert lib.A1 == 0 assert lib.B1 == 1 assert lib.A2 == 0 assert lib.B2 == 1 assert ffi.sizeof("enum e1") == ffi.sizeof("long") assert ffi.sizeof("enum e2") == ffi.sizeof("int") assert repr(ffi.cast("enum e1", 0)) == "<cdata 'enum e1' 0: A1>"
def test_open_array_in_struct(): ffi = FFI() ffi.cdef("struct foo_s { int b; int a[]; };") verify(ffi, 'test_open_array_in_struct', "struct foo_s { int b; int a[]; };") assert ffi.sizeof("struct foo_s") == 4 p = ffi.new("struct foo_s *", [5, [10, 20, 30]]) assert p.a[2] == 30
def test_open_array_in_struct(): ffi = FFI() ffi.cdef("struct foo_s { int b; int a[]; };") verify(ffi, 'test_open_array_in_struct', "struct foo_s { int b; int a[]; };") assert ffi.sizeof("struct foo_s") == 4 p = ffi.new("struct foo_s *", [5, [10, 20, 30]]) assert p.a[2] == 30
def check(self, source, expected_ofs_y, expected_align, expected_size): # NOTE: 'expected_*' is the numbers expected from GCC. # The numbers expected from MSVC are not explicitly written # in this file, and will just be taken from the compiler. ffi = FFI() ffi.cdef("struct s1 { %s };" % source) ctype = ffi.typeof("struct s1") # verify the information with gcc ffi1 = FFI() ffi1.cdef( """ static const int Gofs_y, Galign, Gsize; struct s1 *try_with_value(int fieldnum, long long value); """ ) fnames = [name for name, cfield in ctype.fields if name and cfield.bitsize > 0] setters = ["case %d: s.%s = value; break;" % iname for iname in enumerate(fnames)] lib = ffi1.verify( """ struct s1 { %s }; struct sa { char a; struct s1 b; }; #define Gofs_y offsetof(struct s1, y) #define Galign offsetof(struct sa, b) #define Gsize sizeof(struct s1) struct s1 *try_with_value(int fieldnum, long long value) { static struct s1 s; memset(&s, 0, sizeof(s)); switch (fieldnum) { %s } return &s; } """ % (source, " ".join(setters)) ) if sys.platform == "win32": expected_ofs_y = lib.Gofs_y expected_align = lib.Galign expected_size = lib.Gsize else: assert (lib.Gofs_y, lib.Galign, lib.Gsize) == (expected_ofs_y, expected_align, expected_size) # the real test follows assert ffi.offsetof("struct s1", "y") == expected_ofs_y assert ffi.alignof("struct s1") == expected_align assert ffi.sizeof("struct s1") == expected_size # compare the actual storage of the two for name, cfield in ctype.fields: if cfield.bitsize < 0 or not name: continue if int(ffi.cast(cfield.type, -1)) == -1: # signed min_value = -(1 << (cfield.bitsize - 1)) max_value = (1 << (cfield.bitsize - 1)) - 1 else: min_value = 0 max_value = (1 << cfield.bitsize) - 1 for t in [1, 2, 4, 8, 16, 128, 2813, 89728, 981729, -1, -2, -4, -8, -16, -128, -2813, -89728, -981729]: if min_value <= t <= max_value: self._fieldcheck(ffi, lib, fnames, name, t)
def test_dotdotdot_global_array(): ffi = FFI() ffi.cdef("int aa[...]; int bb[...];") lib = verify(ffi, 'test_dotdotdot_global_array', "int aa[41]; int bb[12];") assert ffi.sizeof(lib.aa) == 41 * 4 assert ffi.sizeof(lib.bb) == 12 * 4 assert lib.aa[40] == lib.bb[11] == 0 py.test.raises(IndexError, "lib.aa[41]") py.test.raises(IndexError, "lib.bb[12]")
def check(self, source, expected_ofs_y, expected_align, expected_size): # NOTE: 'expected_*' is the numbers expected from GCC. # The numbers expected from MSVC are not explicitly written # in this file, and will just be taken from the compiler. ffi = FFI() ffi.cdef("struct s1 { %s };" % source) ctype = ffi.typeof("struct s1") # verify the information with gcc ffi1 = FFI() ffi1.cdef(""" static const int Gofs_y, Galign, Gsize; struct s1 *try_with_value(int fieldnum, long long value); """) fnames = [name for name, cfield in ctype.fields if name and cfield.bitsize > 0] setters = ['case %d: s.%s = value; break;' % iname for iname in enumerate(fnames)] lib = ffi1.verify(""" struct s1 { %s }; struct sa { char a; struct s1 b; }; #define Gofs_y offsetof(struct s1, y) #define Galign offsetof(struct sa, b) #define Gsize sizeof(struct s1) struct s1 *try_with_value(int fieldnum, long long value) { static struct s1 s; memset(&s, 0, sizeof(s)); switch (fieldnum) { %s } return &s; } """ % (source, ' '.join(setters))) if sys.platform == 'win32': expected_ofs_y = lib.Gofs_y expected_align = lib.Galign expected_size = lib.Gsize else: assert (lib.Gofs_y, lib.Galign, lib.Gsize) == ( expected_ofs_y, expected_align, expected_size) # the real test follows assert ffi.offsetof("struct s1", "y") == expected_ofs_y assert ffi.alignof("struct s1") == expected_align assert ffi.sizeof("struct s1") == expected_size # compare the actual storage of the two for name, cfield in ctype.fields: if cfield.bitsize < 0 or not name: continue if int(ffi.cast(cfield.type, -1)) == -1: # signed min_value = -(1 << (cfield.bitsize-1)) max_value = (1 << (cfield.bitsize-1)) - 1 else: min_value = 0 max_value = (1 << cfield.bitsize) - 1 for t in [1, 2, 4, 8, 16, 128, 2813, 89728, 981729, -1,-2,-4,-8,-16,-128,-2813,-89728,-981729]: if min_value <= t <= max_value: self._fieldcheck(ffi, lib, fnames, name, t)
def test_some_float_type(): ffi = FFI() ffi.cdef(""" typedef double... foo_t; typedef float... bar_t; foo_t sum(foo_t[]); bar_t neg(bar_t); """) lib = verify(ffi, 'test_some_float_type', """ typedef float foo_t; static foo_t sum(foo_t x[]) { return x[0] + x[1]; } typedef double bar_t; static double neg(double x) { return -x; } """) assert lib.sum([40.0, 2.25]) == 42.25 assert lib.sum([12.3, 45.6]) != 12.3 + 45.6 # precision loss assert lib.neg(12.3) == -12.3 # no precision loss assert ffi.sizeof("foo_t") == ffi.sizeof("float") assert ffi.sizeof("bar_t") == ffi.sizeof("double")
def test_dotdotdot_global_array(): ffi = FFI() ffi.cdef("int aa[...]; int bb[...];") lib = verify(ffi, 'test_dotdotdot_global_array', "int aa[41]; int bb[12];") assert ffi.sizeof(lib.aa) == 41 * 4 assert ffi.sizeof(lib.bb) == 12 * 4 assert lib.aa[40] == lib.bb[11] == 0 py.test.raises(IndexError, "lib.aa[41]") py.test.raises(IndexError, "lib.bb[12]")
def test_dotdotdot_length_of_array_field(): ffi = FFI() ffi.cdef("struct foo_s { int a[...]; int b[...]; };") verify(ffi, 'test_dotdotdot_length_of_array_field', "struct foo_s { int a[42]; int b[11]; };") assert ffi.sizeof("struct foo_s") == (42 + 11) * 4 p = ffi.new("struct foo_s *") assert p.a[41] == p.b[10] == 0 py.test.raises(IndexError, "p.a[42]") py.test.raises(IndexError, "p.b[11]")
def test_dotdotdot_length_of_array_field(): ffi = FFI() ffi.cdef("struct foo_s { int a[...]; int b[...]; };") verify(ffi, 'test_dotdotdot_length_of_array_field', "struct foo_s { int a[42]; int b[11]; };") assert ffi.sizeof("struct foo_s") == (42 + 11) * 4 p = ffi.new("struct foo_s *") assert p.a[41] == p.b[10] == 0 py.test.raises(IndexError, "p.a[42]") py.test.raises(IndexError, "p.b[11]")
def test_all_primitives(self): ffi = FFI() for name in [ "char", "short", "int", "long", "long long", "signed char", "unsigned char", "unsigned short", "unsigned int", "unsigned long", "unsigned long long", "float", "double", "long double", "wchar_t", "char16_t", "char32_t", "_Bool", "int8_t", "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", "int64_t", "uint64_t", "int_least8_t", "uint_least8_t", "int_least16_t", "uint_least16_t", "int_least32_t", "uint_least32_t", "int_least64_t", "uint_least64_t", "int_fast8_t", "uint_fast8_t", "int_fast16_t", "uint_fast16_t", "int_fast32_t", "uint_fast32_t", "int_fast64_t", "uint_fast64_t", "intptr_t", "uintptr_t", "intmax_t", "uintmax_t", "ptrdiff_t", "size_t", "ssize_t", ]: x = ffi.sizeof(name) assert 1 <= x <= 16
def test_all_primitives(self): ffi = FFI() for name in [ "char", "short", "int", "long", "long long", "signed char", "unsigned char", "unsigned short", "unsigned int", "unsigned long", "unsigned long long", "float", "double", "long double", "wchar_t", "char16_t", "char32_t", "_Bool", "int8_t", "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", "int64_t", "uint64_t", "int_least8_t", "uint_least8_t", "int_least16_t", "uint_least16_t", "int_least32_t", "uint_least32_t", "int_least64_t", "uint_least64_t", "int_fast8_t", "uint_fast8_t", "int_fast16_t", "uint_fast16_t", "int_fast32_t", "uint_fast32_t", "int_fast64_t", "uint_fast64_t", "intptr_t", "uintptr_t", "intmax_t", "uintmax_t", "ptrdiff_t", "size_t", "ssize_t", ]: x = ffi.sizeof(name) assert 1 <= x <= 16
def test_incomplete_struct_as_arg(): ffi = FFI() ffi.cdef("struct foo_s { int x; ...; }; int f(int, struct foo_s);") lib = verify(ffi, "test_incomplete_struct_as_arg", "struct foo_s { int a, x, z; };\n" "int f(int b, struct foo_s s) { return s.x * b; }") s = ffi.new("struct foo_s *", [21]) assert s.x == 21 assert ffi.sizeof(s[0]) == 12 assert ffi.offsetof(ffi.typeof(s), 'x') == 4 assert lib.f(2, s[0]) == 42 assert ffi.typeof(lib.f) == ffi.typeof("int(*)(int, struct foo_s)")
def test_ffi_new_allocator_3(self): ffi = FFI(backend=self.Backend()) seen = [] def myalloc(size): seen.append(size) return ffi.new("char[]", b"X" * size) alloc1 = ffi.new_allocator(myalloc) # no 'free' p1 = alloc1("int[10]") assert seen == [40] assert ffi.typeof(p1) == ffi.typeof("int[10]") assert ffi.sizeof(p1) == 40 assert p1[5] == 0
def test_incomplete_struct_as_arg(): ffi = FFI() ffi.cdef("struct foo_s { int x; ...; }; int f(int, struct foo_s);") lib = verify(ffi, "test_incomplete_struct_as_arg", "struct foo_s { int a, x, z; };\n" "int f(int b, struct foo_s s) { return s.x * b; }") s = ffi.new("struct foo_s *", [21]) assert s.x == 21 assert ffi.sizeof(s[0]) == 12 assert ffi.offsetof(ffi.typeof(s), 'x') == 4 assert lib.f(2, s[0]) == 42 assert ffi.typeof(lib.f) == ffi.typeof("int(*)(int, struct foo_s)")
def test_ffi_new_allocator_3(self): ffi = FFI(backend=self.Backend()) seen = [] def myalloc(size): seen.append(size) return ffi.new("char[]", b"X" * size) alloc1 = ffi.new_allocator(myalloc) # no 'free' p1 = alloc1("int[10]") assert seen == [40] assert ffi.typeof(p1) == ffi.typeof("int[10]") assert ffi.sizeof(p1) == 40 assert p1[5] == 0
def _guess_type(typedef, verify_args, verify_kwargs, assume_pointer=True): if assume_pointer and _is_pointer_sized(typedef, verify_args, verify_kwargs): return '... *' # OK, it's not a pointer, check if it's an arithmetic type ffi = FFI() ffi.cdef("size_t type_size();") try: lib = ffi.verify( verify_args[0] + '\n' + ''' size_t type_size() { ''' + typedef + ''' foo = (''' + typedef + ''') 1; return sizeof(foo); } ''', *verify_args[1:], **verify_kwargs ) size = lib.type_size() # OK, it's an arithmetic type, is it signed or unsigned ffi = FFI() ffi.cdef("size_t type_size();") try: lib = ffi.verify( verify_args[0] + '\n' + ''' size_t type_size() { char arr[((''' + typedef + ''') -1 < 0) * -1]; return sizeof(''' + typedef + '''); } ''', *verify_args[1:], **verify_kwargs ) size = lib.type_size() except VerificationError: # It's a signed type unsigned = '' else: unsigned = 'unsigned ' # Now we know it's an arithmetic type, what's the best size if size <= ffi.sizeof(unsigned + 'char'): return unsigned + 'char' if size <= ffi.sizeof(unsigned + 'short'): return unsigned + 'short' if size <= ffi.sizeof(unsigned + 'int'): return unsigned + 'int' if size <= ffi.sizeof(unsigned + 'long'): return unsigned + 'long' if size <= ffi.sizeof(unsigned + 'long long'): return unsigned + 'long long' if size == ffi.sizeof('void *'): return '... *' else: raise TypeError("Can't figure out the type of {0} with size {1}!".format(typedef, size)) except VerificationError: # it's some kind of struct return 'struct { ...; }'
def compile_sysinfo(): sysinfo_m = """ #include <sys/sysinfo.h> """ sysinfo_h = """ struct sysinfo { long uptime; /* Seconds since boot */ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ unsigned long totalram; /* Total usable main memory size */ unsigned long freeram; /* Available memory size */ unsigned long sharedram; /* Amount of shared memory */ unsigned long bufferram; /* Memory used by buffers */ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* Swap space still available */ unsigned short procs; /* Number of current processes */ unsigned long totalhigh; /* Total high memory size */ unsigned long freehigh; /* Available high memory size */ unsigned int mem_unit; /* Memory unit size in bytes */ %s }; int sysinfo(struct sysinfo *info); """ ffi = FFI() long_size = ffi.sizeof("long") int_size = ffi.sizeof("int") padding = 20 - 2*long_size - int_size if padding > 0: sysinfo_h = sysinfo_h % ("char _f[%i];" % padding) else: sysinfo_h = sysinfo_h % "" ffi.set_source("sysinfo", sysinfo_m) ffi.cdef(sysinfo_h) ffi.compile()
def test_char16_t(self): ffi = FFI() x = ffi.new("char16_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 10 x[2] = u + '\u1324' assert x[2] == u + '\u1324' y = ffi.new("char16_t[]", u + '\u1234\u5678') assert len(y) == 3 assert list(y) == [u + '\u1234', u + '\u5678', u + '\x00'] assert ffi.string(y) == u + '\u1234\u5678' z = ffi.new("char16_t[]", u + '\U00012345') assert len(z) == 3 assert list(z) == [u + '\ud808', u + '\udf45', u + '\x00'] assert ffi.string(z) == u + '\U00012345'
def test_char16_t(self): ffi = FFI() x = ffi.new("char16_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 10 x[2] = u+'\u1324' assert x[2] == u+'\u1324' y = ffi.new("char16_t[]", u+'\u1234\u5678') assert len(y) == 3 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00'] assert ffi.string(y) == u+'\u1234\u5678' z = ffi.new("char16_t[]", u+'\U00012345') assert len(z) == 3 assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00'] assert ffi.string(z) == u+'\U00012345'
def test_misdeclared_field_1(): ffi = FFI() ffi.cdef("struct foo_s { int a[5]; };") try: verify(ffi, 'test_misdeclared_field_1', "struct foo_s { int a[6]; };") except VerificationError: pass # ok, fail during compilation already (e.g. C++) else: assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code p = ffi.new("struct foo_s *") # lazily build the fields and boom: e = py.test.raises(ffi.error, "p.a") assert str(e.value).startswith( "struct foo_s: wrong size for field 'a' " "(cdef says 20, but C compiler says 24)")
def test_misdeclared_field_1(): ffi = FFI() ffi.cdef("struct foo_s { int a[5]; };") try: verify(ffi, 'test_misdeclared_field_1', "struct foo_s { int a[6]; };") except VerificationError: pass # ok, fail during compilation already (e.g. C++) else: assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code p = ffi.new("struct foo_s *") # lazily build the fields and boom: e = py.test.raises(ffi.error, "p.a") assert str(e.value).startswith("struct foo_s: wrong size for field 'a' " "(cdef says 20, but C compiler says 24)")
def __new__(meta, type_name, bases, attrs): if attrs.get('base', False): cls = super().__new__(meta, type_name, bases, attrs) return cls if 'members' in attrs: m = attrs['members'] cls_ffi = FFI() cls_ffi.cdef(build_udt_def(type_name, m)) t = core_ffi.new('GrB_Type*') _check(lib.GrB_Type_new(t, cls_ffi.sizeof(type_name))) cffi_support.map_type(cls_ffi.typeof(type_name), use_record_dtype=True) attrs['ffi'] = cls_ffi attrs['gb_type'] = t[0] attrs['C'] = type_name attrs['member_def'] = list(map(methodcaller('split'), m)) attrs['base_name'] = 'UDT' else: attrs['ffi'] = core_ffi gb_type_name = type_name cls = super().__new__(meta, type_name, bases, attrs) meta._gb_type_map[cls.gb_type] = cls cls.ptr = cls.C + '*' cls.zero = getattr(cls, 'zero', core_ffi.NULL) cls.one = getattr(cls, 'one', core_ffi.NULL) get = partial(getattr, lib) cls.base_name = base_name = getattr(cls, 'base_name', cls.__name__) cls.Monoid_new = get('GrB_Monoid_new_{}'.format(base_name)) cls.Matrix_setElement = get( 'GrB_Matrix_setElement_{}'.format(base_name)) cls.Matrix_extractElement = get( 'GrB_Matrix_extractElement_{}'.format(base_name)) cls.Matrix_extractTuples = get( 'GrB_Matrix_extractTuples_{}'.format(base_name)) cls.Matrix_assignScalar = get('GrB_Matrix_assign_{}'.format(base_name)) cls.Vector_setElement = get( 'GrB_Vector_setElement_{}'.format(base_name)) cls.Vector_extractElement = get( 'GrB_Vector_extractElement_{}'.format(base_name)) cls.Vector_extractTuples = get( 'GrB_Vector_extractTuples_{}'.format(base_name)) cls.Vector_assignScalar = get('GrB_Vector_assign_{}'.format(base_name)) cls.Scalar_setElement = get( 'GxB_Scalar_setElement_{}'.format(base_name)) cls.Scalar_extractElement = get( 'GxB_Scalar_extractElement_{}'.format(base_name)) return cls
def _guess_type(typedef, verify_args, verify_kwargs, assume_pointer=True): if assume_pointer and _is_pointer_sized(typedef, verify_args, verify_kwargs): return '... *' # OK, it's not a pointer, check if it's an arithmetic type ffi = FFI() ffi.cdef("size_t type_size();") try: lib = ffi.verify( verify_args[0] + '\n' + ''' size_t type_size() { ''' + typedef + ''' foo = (''' + typedef + ''') 1; return sizeof(foo); } ''', *verify_args[1:], **verify_kwargs) size = lib.type_size() # OK, it's an arithmetic type, is it signed or unsigned ffi = FFI() ffi.cdef("size_t type_size();") try: lib = ffi.verify( verify_args[0] + '\n' + ''' size_t type_size() { char arr[((''' + typedef + ''') -1 < 0) * -1]; return sizeof(''' + typedef + '''); } ''', *verify_args[1:], **verify_kwargs) size = lib.type_size() except VerificationError: # It's a signed type unsigned = '' else: unsigned = 'unsigned ' # Now we know it's an arithmetic type, what's the best size if size <= ffi.sizeof(unsigned + 'char'): return unsigned + 'char' if size <= ffi.sizeof(unsigned + 'short'): return unsigned + 'short' if size <= ffi.sizeof(unsigned + 'int'): return unsigned + 'int' if size <= ffi.sizeof(unsigned + 'long'): return unsigned + 'long' if size <= ffi.sizeof(unsigned + 'long long'): return unsigned + 'long long' if size == ffi.sizeof('void *'): return '... *' else: raise TypeError( "Can't figure out the type of {0} with size {1}!".format( typedef, size)) except VerificationError: # it's some kind of struct return 'struct { ...; }'
def test_char32_t(self): ffi = FFI() x = ffi.new("char32_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 20 x[3] = u + '\U00013245' assert x[3] == u + '\U00013245' y = ffi.new("char32_t[]", u + '\u1234\u5678') assert len(y) == 3 assert list(y) == [u + '\u1234', u + '\u5678', u + '\x00'] py_uni = u + '\U00012345' z = ffi.new("char32_t[]", py_uni) assert len(z) == 2 assert list(z) == [py_uni, u + '\x00'] # maybe a 2-unichars string assert ffi.string(z) == py_uni if len(py_uni) == 1: # 4-bytes unicodes in Python s = ffi.new("char32_t[]", u + '\ud808\udf00') assert len(s) == 3 assert list(s) == [u + '\ud808', u + '\udf00', u + '\x00']
def test_char32_t(self): ffi = FFI() x = ffi.new("char32_t[]", 5) assert len(x) == 5 and ffi.sizeof(x) == 20 x[3] = u+'\U00013245' assert x[3] == u+'\U00013245' y = ffi.new("char32_t[]", u+'\u1234\u5678') assert len(y) == 3 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00'] py_uni = u+'\U00012345' z = ffi.new("char32_t[]", py_uni) assert len(z) == 2 assert list(z) == [py_uni, u+'\x00'] # maybe a 2-unichars string assert ffi.string(z) == py_uni if len(py_uni) == 1: # 4-bytes unicodes in Python s = ffi.new("char32_t[]", u+'\ud808\udf00') assert len(s) == 3 assert list(s) == [u+'\ud808', u+'\udf00', u+'\x00']
# library_dirs=cfg['library_dirs'], # runtime_library_dirs=cfg['runtime_library_dirs'], # ) _version_info = zmq_version_info() except Exception as e: raise ImportError( "PyZMQ CFFI backend couldn't find zeromq: %s\n" "Please check that you have zeromq headers and libraries." % e) if _version_info < (3, 2, 2): raise ImportError("PyZMQ CFFI backend requires zeromq >= 3.2.2," " but found %i.%i.%i" % _version_info) nsp = new_sizet_pointer = lambda length: ffi.new('size_t*', length) new_uint64_pointer = lambda: (ffi.new('uint64_t*'), nsp(ffi.sizeof('uint64_t')) ) new_int64_pointer = lambda: (ffi.new('int64_t*'), nsp(ffi.sizeof('int64_t'))) new_int_pointer = lambda: (ffi.new('int*'), nsp(ffi.sizeof('int'))) new_binary_data = lambda length: (ffi.new('char[%d]' % (length)), nsp(ffi.sizeof('char') * length)) value_uint64_pointer = lambda val: (ffi.new('uint64_t*', val), ffi.sizeof('uint64_t')) value_int64_pointer = lambda val: (ffi.new('int64_t*', val), ffi.sizeof('int64_t')) value_int_pointer = lambda val: (ffi.new('int*', val), ffi.sizeof('int')) value_binary_data = lambda val, length: (ffi.new('char[%d]' % (length + 1), val), ffi.sizeof('char') * length)
ffi.cdef( """ struct SerializedObject { char name[12]; int a,b; float d,f; }; void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset); int munmap(void *addr, size_t length); """) fileRecords=1024*1024*128 fileSize=ffi.sizeof('struct SerializedObject')*fileRecords f=open('/media/home/test2.dat','rw+b') f.truncate(fileSize) #addr=, length=0, prot=PROT_NONE, flags=MAP_PRIVATE, fd=0, offset=0 #import mmap Maps = ffi.dlopen(None); print "Maps Function:", Maps.mmap MAP_FAILED = ffi.cast( "void*", -1 ) PROT_READ=0x1 PROT_WRITE=0x2
sockopt_functions, polling_functions, extra_functions, ] ) else: raise Exception("Bad ZMQ Install") ffi.cdef(functions) C = ffi.verify( """ #include <stddef.h> #include <string.h> #include <zmq.h> """, libraries=["c", "zmq"], ) nsp = new_sizet_pointer = lambda length: ffi.new("size_t*", length) new_uint64_pointer = lambda: (ffi.new("uint64_t*"), nsp(ffi.sizeof("uint64_t"))) new_int64_pointer = lambda: (ffi.new("int64_t*"), nsp(ffi.sizeof("int64_t"))) new_int_pointer = lambda: (ffi.new("int*"), nsp(ffi.sizeof("int"))) new_binary_data = lambda length: (ffi.new("char[%d]" % (length)), nsp(ffi.sizeof("char") * length)) value_uint64_pointer = lambda val: (ffi.new("uint64_t*", val), ffi.sizeof("uint64_t")) value_int64_pointer = lambda val: (ffi.new("int64_t*", val), ffi.sizeof("int64_t")) value_int_pointer = lambda val: (ffi.new("int*", val), ffi.sizeof("int")) value_binary_data = lambda val, length: (ffi.new("char[%d]" % (length), val), ffi.sizeof("char") * length)
# if we have multiple signals then all is good try: signals = iter(signals) except TypeError: # if not make the value iterable signals = [signals] for signal in signals: C.sigaddset(new_sigmask, signal) ret = C.pthread_sigmask(action, new_sigmask, ffi.NULL) if ret < 0: err = ffi.errno if err == errno.EINVAL: raise ValueError("Action is an invalid value (not one of SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK)") elif err == errno.EFAULT: raise ValueError("sigmask is not a valid sigset_t") else: # If you are here, its a bug. send us the traceback raise UnknownError(err) signum_to_signame = {val:key for key, val in signal.__dict__.items() if isinstance(val, int) and "_" not in key} #SIGINFO_LENGTH = 128 # Bytes SIGINFO_LENGTH = ffi.sizeof('struct signalfd_siginfo')
class RimeConstDefinition(object): """ Holds the cffi object defining the C structure of the RIME constant data which will be passed to GPUs. """ def __init__(self, slvr): self._ffi = FFI() # Parse the structure self._cstr = self._struct(slvr) self._ffi.cdef(self._struct(slvr)) @staticmethod def _struct(slvr): """ Returns a string containing the C definition of the RIME constant data structure """ def _emit_struct_field_str(name): return _SPACE + '{t} {n};'.format(t=_FIELD_TYPE, n=name) # Define our field structure. Looks something like # typedef struct { # unsigned int global_size; # unsigned int local_size; # unsigned int extents[2]; # } _FIELD_TYPE; l = ['typedef struct {'] l.extend([_SPACE + 'unsigned int {n};'.format(n=n) for n in ('global_size', 'local_size', 'lower_extent', 'upper_extent')]) l.append('}} {t};'.format(t=_FIELD_TYPE)) # Define our constant data structure. Looks something like # typedef struct { # _FIELD_TYPE ntime; # _FIELD_TYPE na; # .... # } _STRUCT_TYPE; l.append('typedef struct {') l.extend([_emit_struct_field_str(n) for n in slvr.dimensions().iterkeys()]) l.append('} ' + _STRUCT_TYPE + ';') # Join with newlines and return the string return '\n'.join(l) def struct_size(self): """ Returns the size in bytes of the RIME constant data structure """ return self._ffi.sizeof(_STRUCT_TYPE) def wrap(self, ndary): assert ndary.nbytes == self.struct_size(), \ ('The size of the supplied array {as} does ' 'not match that of the constant data structure {ds}.') \ .format(ws=ndary.nbytes, ds=self.struct_size()) # Create a cdata object by wrapping ndary # and cast to the structure type return self._ffi.cast(_STRUCT_PTR_TYPE, self._ffi.from_buffer(ndary)) def __str__(self): return self._cstr
def test_sizeof(): ffi = FFI() assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
int next_index; int color; float policy[362]; float next_policy[362]; float ownership[361]; int winner; int number; float komi; } Example; void set_seed(int seed); int extract_single_example(const char*, Example*); """) COMPLEX_LIB = load_shared_library(COMPLEX_FFI) FEATURE_SIZE = get_num_features() * 361 * COMPLEX_FFI.sizeof('short') POLICY_SIZE = 362 * COMPLEX_FFI.sizeof('float') OWNERSHIP_SIZE = 361 * COMPLEX_FFI.sizeof('float') def set_seed(seed): """ Sets the seed of the extraction """ COMPLEX_LIB.set_seed(seed) def get_single_example(line): """ Returns a single example, from the given SGF file. """ raw_example = COMPLEX_FFI.new('Example[]', 1) result = COMPLEX_LIB.extract_single_example(line, raw_example) if result == 0:
def test_verify_typedef(): ffi = FFI() ffi.cdef("typedef int **foo_t;") lib = verify(ffi, 'test_verify_typedef', 'typedef int **foo_t;') assert ffi.sizeof("foo_t") == ffi.sizeof("void *")
def test_sizeof(): ffi = FFI() assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
#include <zmq.h> #include <zmq_utils.h> #include "zmq_compat.h" int get_ipc_path_max_len(void) { struct sockaddr_un *dummy; return sizeof(dummy->sun_path) - 1; } ''', libraries=['c', 'zmq'], include_dirs=[zmq_utils]) nsp = new_sizet_pointer = lambda length: ffi.new('size_t*', length) new_uint64_pointer = lambda: (ffi.new('uint64_t*'), nsp(ffi.sizeof('uint64_t'))) new_int64_pointer = lambda: (ffi.new('int64_t*'), nsp(ffi.sizeof('int64_t'))) new_int_pointer = lambda: (ffi.new('int*'), nsp(ffi.sizeof('int'))) new_binary_data = lambda length: (ffi.new('char[%d]' % (length)), nsp(ffi.sizeof('char') * length)) value_uint64_pointer = lambda val : (ffi.new('uint64_t*', val), ffi.sizeof('uint64_t')) value_int64_pointer = lambda val: (ffi.new('int64_t*', val), ffi.sizeof('int64_t')) value_int_pointer = lambda val: (ffi.new('int*', val), ffi.sizeof('int')) value_binary_data = lambda val, length: (ffi.new('char[%d]' % (length + 1), val), ffi.sizeof('char') * length)
class _PcapFfi(object): """ This class represents the low-level interface to the libpcap library. It encapsulates all the cffi calls and C/Python conversions, as well as translation of errors and error codes to PcapExceptions. It is intended to be used as a singleton class through the PcapDumper and PcapLiveDevice classes, below. """ _instance = None __slots__ = ['_ffi', '_libpcap', '_interfaces', '_windows'] def __init__(self): """ Assumption: this class is instantiated once in the main thread before any other threads have a chance to try instantiating it. """ if _PcapFfi._instance: raise Exception("Can't initialize this class more than once!") _PcapFfi._instance = self self._windows = False self._ffi = FFI() self._ffi.cdef(cc_ndpi_network_headers, override=True, packed=True) if "win" in sys.platform[:3]: raise PcapException('Windows OS is not currently supported.') elif sys.platform == 'darwin': self._ffi.cdef(cc_libpcap_structure.replace( 'apple_additional', 'char comment[256];'), override=True) libname = '/libs/libpcap.so' else: self._ffi.cdef(cc_libpcap_structure.replace( 'apple_additional', ''), override=True) libname = '/libs/libpcap.so' try: self._ffi.cdef(cc_libpcap_apis, override=True) self._libpcap = self._ffi.dlopen( dirname(abspath(__file__)) + libname) except Exception as e: raise PcapException("Error opening libpcap: {}".format(e)) self._interfaces = [] self.discoverdevs() @staticmethod def instance(): if not _PcapFfi._instance: _PcapFfi._instance = _PcapFfi() return _PcapFfi._instance @property def version(self): return self._ffi.string(self._libpcap.pcap_lib_version()) def discoverdevs(self): """ Find all the pcap-eligible devices on the local system """ if len(self._interfaces): raise PcapException("Device discovery should only be done once.") ppintf = self._ffi.new("pcap_if_t * *") errbuf = self._ffi.new("char []", 128) rv = self._libpcap.pcap_findalldevs(ppintf, errbuf) if rv: raise PcapException("pcap_findalldevs returned failure: {}".format( self._ffi.string(errbuf))) pintf = ppintf[0] tmp = pintf pindex = 0 while tmp != self._ffi.NULL: xname = self._ffi.string( tmp.name) # "internal name"; still stored as bytes object xname = xname.decode('ascii', 'ignore') if self._windows: ext_name = "port{}".format(pindex) else: ext_name = xname pindex += 1 if tmp.description == self._ffi.NULL: xdesc = ext_name else: xdesc = self._ffi.string(tmp.description) xdesc = xdesc.decode('ascii', 'ignore') # NB: on WinPcap, only loop flag is set isloop = (tmp.flags & 0x1) == 0x1 isup = (tmp.flags & 0x2) == 0x2 isrunning = (tmp.flags & 0x4) == 0x4 xif = PcapInterface(ext_name, xname, xdesc, isloop, isup, isrunning) self._interfaces.append(xif) tmp = tmp.next self._libpcap.pcap_freealldevs(pintf) @property def devices(self): return self._interfaces @property def lib(self): return self._libpcap @property def ffi(self): return self._ffi def _parse_packet(self, xdev, header, packet, nroots): # MPLS header mpls = self._ffi.new("union mpls *") # IP header iph = self._ffi.new("struct ndpi_iphdr *") # IPv6 header iph6 = self._ffi.new("struct ndpi_ipv6hdr *") # lengths and offsets eth_offset, ether_type, wifi_len, pyld_eth_len, ip_offset, frag_off, vlan_id = 0, 0, 0, 0, 0, 0, 0 time = (header.tv_sec * TICK_RESOLUTION) + (header.tv_usec / (1000000 / TICK_RESOLUTION)) dlt = self._libpcap.pcap_datalink(xdev) datalink_check = True while datalink_check: datalink_check = False if header.caplen < (40 + eth_offset): return None # too short if Dlt(dlt) == Dlt.DLT_NULL: tmp_dlt_null = self._ffi.cast('struct ptr_uint32 *', packet + eth_offset) if int(ntohs(tmp_dlt_null.value)) == 2: ether_type = 0x0800 else: ether_type = 0x86dd ip_offset = 4 + eth_offset elif (Dlt(dlt) == Dlt.DLT_C_HDLC) or ( Dlt(dlt) == Dlt.DLT_PPP) or Dlt(dlt) == Dlt.DLT_PPP_SERIAL: chdlc = self._ffi.cast('struct ndpi_chdlc *', packet + eth_offset) ip_offset = self._ffi.sizeof('struct ndpi_chdlc') ether_type = ntohs(chdlc.proto_code) elif Dlt(dlt) == Dlt.DLT_EN10MB: # IEEE 802.3 Ethernet - 1 */ ethernet = self._ffi.cast('struct ndpi_ethhdr *', packet + eth_offset) ip_offset = self._ffi.sizeof('struct ndpi_ethhdr') + eth_offset check = ntohs(ethernet.h_proto) if check <= 1500: pyld_eth_len = check elif check >= 1536: ether_type = check if pyld_eth_len != 0: llc = self._ffi.cast('struct ndpi_llc_header_snap *', packet + ip_offset) if (llc.dsap == 0xaa) or ( llc.ssap == 0xaa): # check for LLC layer with SNAP ext ether_type = llc.snap.proto_ID ip_offset += 8 elif (llc.dsap == 0x42) or (llc.ssap == 0x42): # No SNAP ext return None elif Dlt(dlt) == Dlt.DLT_LINUX_SLL: # Linux Cooked Capture - 113 ether_type = ( packet[eth_offset + 14] << 8) + packet[eth_offset + 15] ip_offset = 16 + eth_offset elif Dlt( dlt ) == Dlt.DLT_IEEE802_11_RADIO: # Radiotap link-layer - 127 radiotap = self._ffi.cast('struct ndpi_radiotap_header *', packet + eth_offset) radio_len = radiotap.len if (radiotap.flags & 0x50) == 0x50: # Check Bad FCS presence return None if header.caplen < ( eth_offset + radio_len + self._ffi.sizeof('struct ndpi_wifi_header')): return None # Calculate 802.11 header length(variable) wifi = self._ffi.cast('struct ndpi_wifi_header *', packet + (eth_offset + radio_len)) fc = wifi.fc # Check wifi data presence if fcf_type(fc) == 0x2: if (fcf_to_ds(fc) and fcf_from_ds(fc) == 0x0) or ( fcf_to_ds(fc) == 0x0 and fcf_from_ds(fc)): wifi_len = 26 # + 4 byte fcs # Check ether_type from LLC llc = self._ffi.cast( 'struct ndpi_llc_header_snap *', packet + (eth_offset + wifi_len + radio_len)) if llc.dsap == 0xaa: ether_type = ntohs(llc.snap.proto_ID) # Set IP header offset ip_offset = wifi_len + radio_len + self._ffi.sizeof( 'struct ndpi_llc_header_snap') + eth_offset elif Dlt(dlt) == Dlt.DLT_RAW: ip_offset, eth_offset = 0, 0 else: return None ether_type_check = True while ether_type_check: ether_type_check = False if ether_type == 0x8100: vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset + 1]) & 0xFFF ether_type = ( packet[ip_offset + 2] << 8) + packet[ip_offset + 3] ip_offset += 4 while ether_type == 0x8100 and ip_offset < header.caplen: # Double tagging for 802.1Q vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset + 1]) & 0xFFF ether_type = ( packet[ip_offset + 2] << 8) + packet[ip_offset + 3] ip_offset += 4 ether_type_check = True elif (ether_type == 0x8847) or (ether_type == 0x8848): tmp_u32 = self._ffi.cast('struct ptr_uint32 *', packet + ip_offset) mpls.u32 = int(ntohl(tmp_u32.value)) ether_type = 0x0800 ip_offset += 4 while not mpls.mpls.s: tmp_u32_loop = self._ffi.cast('struct ptr_uint32 *', packet + ip_offset) mpls.u32 = int(ntohl(tmp_u32_loop.value)) ip_offset += 4 ether_type_check = True elif ether_type == 0x8864: ether_type = 0x0800 ip_offset += 8 ether_type_check = True else: pass ip_check = True while ip_check: ip_check = False if header.caplen < (ip_offset + self._ffi.sizeof('struct ndpi_iphdr')): return None # too short for next IP header iph = self._ffi.cast('struct ndpi_iphdr *', packet + ip_offset) if (ether_type == 0x0800) and ( header.caplen >= ip_offset): # work on Ethernet packets that contain IP frag_off = ntohs(iph.frag_off) if header.caplen < header.len: print( "WARNING: packet capture size is smaller than packet size," ) if iph.version == 4: ip_len = iph.ihl * 4 iph6 = self._ffi.NULL if iph.protocol == 41: # IPPROTO_IPV6 ip_offset += ip_len if ip_len > 0: ip_check = True if (frag_off & 0x1FFF) != 0: return None elif iph.version == 6: if header.caplen < ( ip_offset + self._ffi.sizeof('struct ndpi_ipv6hdr')): return None # too short for IPv6 header iph6 = self._ffi.cast('struct ndpi_ipv6hdr *', packet + ip_offset) ip_len = self._ffi.sizeof('struct ndpi_ipv6hdr') if iph6.ip6_hdr.ip6_un1_nxt == 60: # IPv6 destination option options = self._ffi.cast('uint8_t *', packet + (ip_offset + ip_len)) ip_len += 8 * (options[1] + 1) iph = self._ffi.NULL else: return None return process_packet(self._ffi, time, vlan_id, iph, iph6, header.caplen - ip_offset, header.caplen, nroots) def _recv_packet(self, xdev, nroots=1): phdr = self._ffi.new("struct pcap_pkthdr **") pdata = self._ffi.new("unsigned char **") rv = self._libpcap.pcap_next_ex(xdev, phdr, pdata) if rv == 1: return self._parse_packet(xdev, phdr[0], pdata[0], nroots) elif rv == 0: # timeout; nothing to return return 0 elif rv == -1: # error on receive; raise an exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException("Error receiving packet: {}".format(s)) elif rv == -2: # reading from savefile, but none left return -2
def test_verify_typedef(): ffi = FFI() ffi.cdef("typedef int **foo_t;") lib = verify(ffi, 'test_verify_typedef', 'typedef int **foo_t;') assert ffi.sizeof("foo_t") == ffi.sizeof("void *")
int get_ipc_path_max_len(void) { struct sockaddr_un *dummy; return sizeof(dummy->sun_path) - 1; } ''', libraries=cfg['libraries'], include_dirs=cfg['include_dirs'], library_dirs=cfg['library_dirs'], runtime_library_dirs=cfg['runtime_library_dirs'], ) nsp = new_sizet_pointer = lambda length: ffi.new('size_t*', length) new_uint64_pointer = lambda: (ffi.new('uint64_t*'), nsp(ffi.sizeof('uint64_t'))) new_int64_pointer = lambda: (ffi.new('int64_t*'), nsp(ffi.sizeof('int64_t'))) new_int_pointer = lambda: (ffi.new('int*'), nsp(ffi.sizeof('int'))) new_binary_data = lambda length: (ffi.new('char[%d]' % (length)), nsp(ffi.sizeof('char') * length)) value_uint64_pointer = lambda val : (ffi.new('uint64_t*', val), ffi.sizeof('uint64_t')) value_int64_pointer = lambda val: (ffi.new('int64_t*', val), ffi.sizeof('int64_t')) value_int_pointer = lambda val: (ffi.new('int*', val), ffi.sizeof('int')) value_binary_data = lambda val, length: (ffi.new('char[%d]' % (length + 1), val), ffi.sizeof('char') * length)
""") # include/R_exts/Complex.h ffibuilder.cdef(""" typedef struct { double r; double i; } Rcomplex; """) # include/Rinternals.h ffibuilder.cdef(""" typedef int R_len_t; """) if ffibuilder.sizeof('size_t') > 4: LONG_VECTOR_SUPPORT = True R_XLEN_T_MAX = 4503599627370496 R_SHORT_LEN_MAX = 2147483647 ffibuilder.cdef(""" typedef ptrdiff_t R_xlen_t; """) else: ffibuilder.cdef(""" typedef int R_xlen_t; """) ffibuilder.cdef(""" double R_NaN; /* IEEE NaN */ double R_NaReal; /* NA_REAL: IEEE */ int R_NaInt;
class _PcapFfi(object): """ This class represents the low-level interface to the libpcap library. It encapsulates all the cffi calls and C/Python conversions, as well as translation of errors and error codes to PcapExceptions. It is intended to be used as a singleton class through the PcapDumper and PcapLiveDevice classes, below. """ _instance = None __slots__ = ['_ffi', '_libpcap', '_interfaces', '_windows'] def __init__(self): """ Assumption: this class is instantiated once in the main thread before any other threads have a chance to try instantiating it. """ if _PcapFfi._instance: raise Exception("Can't initialize this class more than once!") _PcapFfi._instance = self self._windows = False self._ffi = FFI() self._ffi.cdef(cc, override=True) self._ffi.cdef(cc_packed, override=True, packed=1) if sys.platform == 'darwin': libname = 'libpcap.dylib' elif "win" in sys.platform[:3]: libname = 'wpcap.dll' # winpcap self._windows = True else: # if not macOS (darwin) or windows, assume we're on # some unix-based system and try for libpcap.so libname = 'libpcap.so' try: self._libpcap = self._ffi.dlopen(libname) except Exception as e: raise PcapException("Error opening libpcap: {}".format(e)) self._interfaces = [] self.discoverdevs() @staticmethod def instance(): if not _PcapFfi._instance: _PcapFfi._instance = _PcapFfi() return _PcapFfi._instance @property def version(self): return self._ffi.string(self._libpcap.pcap_lib_version()) def discoverdevs(self): """ Find all the pcap-eligible devices on the local system. """ if len(self._interfaces): raise PcapException("Device discovery should only be done once.") ppintf = self._ffi.new("pcap_if_t * *") errbuf = self._ffi.new("char []", 128) rv = self._libpcap.pcap_findalldevs(ppintf, errbuf) if rv: raise PcapException("pcap_findalldevs returned failure: {}".format( self._ffi.string(errbuf))) pintf = ppintf[0] tmp = pintf pindex = 0 while tmp != self._ffi.NULL: xname = self._ffi.string( tmp.name) # "internal name"; still stored as bytes object xname = xname.decode('ascii', 'ignore') if self._windows: ext_name = "port{}".format(pindex) else: ext_name = xname pindex += 1 if tmp.description == self._ffi.NULL: xdesc = ext_name else: xdesc = self._ffi.string(tmp.description) xdesc = xdesc.decode('ascii', 'ignore') # NB: on WinPcap, only loop flag is set isloop = (tmp.flags & 0x1) == 0x1 isup = (tmp.flags & 0x2) == 0x2 isrunning = (tmp.flags & 0x4) == 0x4 xif = PcapInterface(ext_name, xname, xdesc, isloop, isup, isrunning) self._interfaces.append(xif) tmp = tmp.next self._libpcap.pcap_freealldevs(pintf) @property def devices(self): return self._interfaces @property def lib(self): return self._libpcap @property def ffi(self): return self._ffi def _process_packet(self, xdev, header, packet, nroots): # MPLS header mpls = self._ffi.new("union mpls *") # IP header iph = self._ffi.new("struct nfstream_iphdr *") # IPv6 header iph6 = self._ffi.new("struct nfstream_ipv6hdr *") # lengths and offsets eth_offset = 0 radio_len = 0 fc = 0 type = 0 wifi_len = 0 pyld_eth_len = 0 check = 0 ip_offset = 0 ip_len = 0 frag_off = 0 vlan_id = 0 proto = 0 time = 0 time = (header.tv_sec * TICK_RESOLUTION) + (header.tv_usec / (1000000 / TICK_RESOLUTION)) datalink_type = self._libpcap.pcap_datalink(xdev) datalink_check = True while datalink_check: datalink_check = False if Dlt(datalink_type) == Dlt.DLT_NULL: tmp_dlt_null = self._ffi.cast('struct pp_32 *', packet + eth_offset) if int(ntohs(tmp_dlt_null.value)) == 2: type = 0x0800 else: type = 0x86dd ip_offset = 4 + eth_offset elif Dlt( datalink_type ) == Dlt.DLT_PPP_SERIAL: # Cisco PPP in HDLC - like framing - 50 chdlc = self._ffi.cast('struct nfstream_chdlc *', packet + eth_offset) ip_offset = self._ffi.sizeof( 'struct nfstream_chdlc') # CHDLC_OFF = 4 type = ntohs(chdlc.proto_code) elif (Dlt(datalink_type) == Dlt.DLT_C_HDLC) or ( Dlt(datalink_type) == Dlt.DLT_PPP): # Cisco PPP - 9 or 104 chdlc = self._ffi.cast('struct nfstream_chdlc *', packet + eth_offset) # CHDLC_OFF = 4 ip_offset = self._ffi.sizeof( 'struct nfstream_chdlc') # CHDLC_OFF = 4 type = ntohs(chdlc.proto_code) elif Dlt(datalink_type ) == Dlt.DLT_EN10MB: # IEEE 802.3 Ethernet - 1 */ ethernet = self._ffi.cast('struct nfstream_ethhdr *', packet + eth_offset) ip_offset = self._ffi.sizeof( 'struct nfstream_ethhdr') + eth_offset check = ntohs(ethernet.h_proto) if check <= 1500: pyld_eth_len = check elif check >= 1536: type = check if pyld_eth_len != 0: llc = self._ffi.cast('struct nfstream_llc_header_snap *', packet + ip_offset) if (llc.dsap == 0xaa) or ( llc.ssap == 0xaa): # check for LLC layer with SNAP ext type = llc.snap.proto_ID ip_offset += 8 elif (llc.dsap == 0x42) or (llc.ssap == 0x42): # No SNAP ext return None elif Dlt(datalink_type ) == Dlt.DLT_LINUX_SLL: # Linux Cooked Capture - 113 type = (packet[eth_offset + 14] << 8) + packet[eth_offset + 15] ip_offset = 16 + eth_offset elif Dlt( datalink_type ) == Dlt.DLT_IEEE802_11_RADIO: # Radiotap link - layer - 127 radiotap = self._ffi.cast('struct nfstream_radiotap_header *', packet + eth_offset) radio_len = radiotap.len if (radiotap.flags & 0x50) == 0x50: # Check Bad FCS presence return None # Calculate 802.11 header length(variable) wifi = self._ffi.cast('struct nfstream_wifi_header *', packet + (eth_offset + radio_len)) fc = wifi.fc # Check wifi data presence if fcf_type(fc) == 0x2: if (fcf_to_ds(fc) and fcf_from_ds(fc) == 0x0) or ( fcf_to_ds(fc) == 0x0 and fcf_from_ds(fc)): wifi_len = 26 # + 4 byte fcs else: pass # Check ether_type from LLC llc = self._ffi.cast( 'struct nfstream_llc_header_snap *', packet + (eth_offset + wifi_len + radio_len)) if llc.dsap == 0xaa: type = ntohs(llc.snap.proto_ID) # Set IP header offset ip_offset = wifi_len + radio_len + self._ffi.sizeof( 'struct nfstream_llc_header_snap') + eth_offset elif Dlt(datalink_type) == Dlt.DLT_RAW: ip_offset = 0 eth_offset = 0 else: return None ether_type_check = True while ether_type_check: ether_type_check = False if type == 0x8100: vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset + 1]) & 0xFFF type = (packet[ip_offset + 2] << 8) + packet[ip_offset + 3] ip_offset += 4 while type == 0x8100 and ip_offset < header.caplen: # Double tagging for 802.1Q vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset + 1]) & 0xFFF type = ( packet[ip_offset + 2] << 8) + packet[ip_offset + 3] ip_offset += 4 ether_type_check = True elif (type == 0x8847) or (type == 0x8848): tmp_u32 = self._ffi.cast('struct pp_32 *', packet + ip_offset) mpls.u32 = int(ntohl(tmp_u32.value)) type = 0x0800 ip_offset += 4 while not mpls.mpls.s: tmp_u32_loop = self._ffi.cast('struct pp_32 *', packet + ip_offset) mpls.u32 = int(ntohl(tmp_u32_loop.value)) ip_offset += 4 ether_type_check = True elif type == 0x8864: type = 0x0800 ip_offset += 8 ether_type_check = True else: pass ip_check = True while ip_check: ip_check = False # Check and set IP header size and total packet length iph = self._ffi.cast('struct nfstream_iphdr *', packet + ip_offset) # Just work on Ethernet packets that contain IP if (type == 0x0800) and (header.caplen >= ip_offset): frag_off = ntohs(iph.frag_off) if header.caplen < header.len: pass if iph.version == 4: ip_len = iph.ihl * 4 iph6 = self._ffi.NULL if iph.protocol == 41: # IPPROTO_IPV6 ip_offset += ip_len ip_check = True if (frag_off & 0x1FFF) != 0: return None elif iph.version == 6: iph6 = self._ffi.cast('struct nfstream_ipv6hdr *', packet + ip_offset) ip_len = self._ffi.sizeof('struct nfstream_ipv6hdr') if iph6.ip6_hdr.ip6_un1_nxt == 60: # IPv6 destination option options = self._ffi.cast('uint8_t *', packet + (ip_offset + ip_len)) ip_len += 8 * (options[1] + 1) iph = self._ffi.NULL else: return None l4_offset = 0 ipsize = 0 src_addr = 0 dst_addr = 0 l4_packet_len = 0 version = 0 nfstream_hash = 0 if iph6 == self._ffi.NULL: version = 4 l4_packet_len = ntohs(iph.tot_len) - (iph.ihl * 4) ipsize = header.caplen - ip_offset proto = iph.protocol src_addr = ntohl(iph.saddr) dst_addr = ntohl(iph.daddr) nfstream_hash += iph.saddr + iph.daddr + proto + vlan_id else: version = 6 src_addr = ntohl(iph6.ip6_src.u6_addr.u6_addr32[0]) << 96 | ntohl( iph6.ip6_src.u6_addr.u6_addr32[1]) << 64 | ntohl( iph6.ip6_src.u6_addr.u6_addr32[2]) << 32 | ntohl( iph6.ip6_src.u6_addr.u6_addr32[3]) dst_addr = ntohl(iph6.ip6_dst.u6_addr.u6_addr32[0]) << 96 | ntohl( iph6.ip6_dst.u6_addr.u6_addr32[1]) << 64 | ntohl( iph6.ip6_dst.u6_addr.u6_addr32[2]) << 32 | ntohl( iph6.ip6_dst.u6_addr.u6_addr32[3]) proto = iph6.ip6_hdr.ip6_un1_nxt if proto == 60: options = self._ffi.cast( 'uint8_t *', iph6) + self._ffi.sizeof('struct nfstream_ipv6hdr') proto = options[0] l4_packet_len = ntohs(iph6.ip6_hdr.ip6_un1_plen) nfstream_hash += ( iph6.ip6_src.u6_addr.u6_addr32[2] + iph6.ip6_src.u6_addr.u6_addr32[3]) + ( iph6.ip6_dst.u6_addr.u6_addr32[2] + iph6.ip6_dst.u6_addr.u6_addr32[3]) + proto + vlan_id if version == 4: if ipsize < 20: return None if ((iph.ihl * 4) > ipsize) or (ipsize < ntohs(iph.tot_len)): return None l4_offset = iph.ihl * 4 l3 = self._ffi.cast('uint8_t *', iph) else: l4_offset = self._ffi.sizeof('struct nfstream_ipv6hdr') l3 = self._ffi.cast('uint8_t *', iph6) l4 = self._ffi.cast('uint8_t *', l3) + l4_offset syn, cwr, ece, urg, ack, psh, rst, fin = 0, 0, 0, 0, 0, 0, 0, 0 if (proto == 6 ) and l4_packet_len >= self._ffi.sizeof('struct nfstream_tcphdr'): tcph = self._ffi.cast('struct nfstream_tcphdr *', l4) sport = int(ntohs(tcph.source)) dport = int(ntohs(tcph.dest)) syn = int(tcph.syn) cwr = int(tcph.cwr) ece = int(tcph.ece) urg = int(tcph.urg) ack = int(tcph.ack) psh = int(tcph.psh) rst = int(tcph.rst) fin = int(tcph.fin) elif (proto == 17) and l4_packet_len >= self._ffi.sizeof( 'struct nfstream_udphdr'): udph = self._ffi.cast('struct nfstream_udphdr *', l4) sport = int(ntohs(udph.source)) dport = int(ntohs(udph.dest)) else: sport = 0 dport = 0 nfstream_hash += sport + dport if version == 4: return NFPacket(time=int(time), capture_length=header.caplen, length=header.len, nfhash=nfstream_hash, ip_src=src_addr, ip_dst=dst_addr, src_port=sport, dst_port=dport, protocol=proto, vlan_id=vlan_id, version=version, tcpflags=tcpflags(syn=syn, cwr=cwr, ece=ece, urg=urg, ack=ack, psh=psh, rst=rst, fin=fin), raw=bytes(xffi.buffer(iph, ipsize)), root_idx=nfstream_hash % nroots) else: return NFPacket(time=int(time), capture_length=header.caplen, length=header.len, nfhash=nfstream_hash, ip_src=src_addr, ip_dst=dst_addr, src_port=sport, dst_port=dport, protocol=proto, vlan_id=vlan_id, version=version, tcpflags=tcpflags(syn=syn, cwr=cwr, ece=ece, urg=urg, ack=ack, psh=psh, rst=rst, fin=fin), raw=bytes(xffi.buffer(iph6, header.len - ip_offset)), root_idx=nfstream_hash % nroots) def _recv_packet(self, xdev, nroots=1): phdr = self._ffi.new("struct pcap_pkthdr **") pdata = self._ffi.new("unsigned char **") rv = self._libpcap.pcap_next_ex(xdev, phdr, pdata) if rv == 1: return self._process_packet(xdev, phdr[0], pdata[0], nroots) elif rv == 0: # timeout; nothing to return return 0 elif rv == -1: # error on receive; raise an exception s = self._ffi.string(self._libpcap.pcap_geterr(xdev)) raise PcapException("Error receiving packet: {}".format(s)) elif rv == -2: # reading from savefile, but none left return -2
class RimeConstDefinition(object): """ Holds the cffi object defining the C structure of the RIME constant data which will be passed to GPUs. """ def __init__(self, slvr): self._ffi = FFI() # Parse the structure self._cstr = self._struct(slvr) self._ffi.cdef(self._struct(slvr)) @staticmethod def _struct(slvr): """ Returns a string containing the C definition of the RIME constant data structure """ def _emit_struct_field_str(name): return _SPACE + '{t} {n};'.format(t=_FIELD_TYPE, n=name) # Define our field structure. Looks something like # typedef struct { # unsigned int global_size; # unsigned int local_size; # unsigned int extents[2]; # } _FIELD_TYPE; l = ['typedef struct {'] l.extend([ _SPACE + 'unsigned int {n};'.format(n=n) for n in ('global_size', 'local_size', 'lower_extent', 'upper_extent') ]) l.append('}} {t};'.format(t=_FIELD_TYPE)) # Define our constant data structure. Looks something like # typedef struct { # _FIELD_TYPE ntime; # _FIELD_TYPE na; # .... # } _STRUCT_TYPE; l.append('typedef struct {') l.extend( [_emit_struct_field_str(n) for n in slvr.dimensions().iterkeys()]) l.append('} ' + _STRUCT_TYPE + ';') # Join with newlines and return the string return '\n'.join(l) def struct_size(self): """ Returns the size in bytes of the RIME constant data structure """ return self._ffi.sizeof(_STRUCT_TYPE) def wrap(self, ndary): assert ndary.nbytes == self.struct_size(), \ ('The size of the supplied array {as} does ' 'not match that of the constant data structure {ds}.') \ .format(ws=ndary.nbytes, ds=self.struct_size()) # Create a cdata object by wrapping ndary # and cast to the structure type return self._ffi.cast(_STRUCT_PTR_TYPE, self._ffi.from_buffer(ndary)) def __str__(self): return self._cstr
#!/usr/bin/env python # -*- coding:UTF-8 -*- """Example of interaction between C code and numpy using cffi @author: Nicolas Iooss """ from cffi import FFI import numpy import os.path import sys ffi = FFI() SIZEOF_DOUBLE = ffi.sizeof('double') current_dir = os.path.dirname(__file__) or os.path.curdir with open(os.path.join(current_dir, 'cffi_example.h'), 'r') as fhead: ffi.cdef(''.join([ line.replace('CFFI_EXAMPLE_API', '') for line in fhead if not line.lstrip().startswith('#')])) filepath = os.path.join(current_dir, '_cffi_example') if os.name == 'nt': filepath += '.dll' elif os.name == 'posix': filepath += '.so' else: raise RuntimeError("Unknown OS {}".format(os.name)) _cffi_example = ffi.dlopen(filepath) def get_matrix_stride(mat): """Get the stride between lines of a C matrix""" itemsize = mat.itemsize
ffi.set_source("moco._ffi_moco_packet", None, libraries=[]) dpt_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), '../../embedded/firmware/communication/data_packet_types.h') with open(dpt_path, 'r') as dpt_file: ffi_data = dpt_file.readlines() ffi.cdef(''.join(ffi_data[7:-2])) import six from .util.datatypes import update, set_values, AttributeDict logger = logging.getLogger("Motive." + __name__) MAX_DATA_SIZE = 512 ffi = ffi PACKET_LEN = ffi.sizeof("GenericPacket") PACKET_HEADER_LEN = ffi.sizeof("PacketHeader") PACKET_DATA_LEN = ffi.sizeof("GenericData") DATA_FMT = ffi.typeof("DataFormats").relements DATA_FMT_INT = ffi.typeof("DataFormats").elements dp = AttributeDict(DATA_FMT) dp.PACKET_VERSION = 2 PACKET_SIGNATURE = struct.unpack('I', b"MPD" + str(dp.PACKET_VERSION).encode())[0] class Packet(object): def __init__(self): self.header = ffi.new("PacketHeader *") self.data = ffi.new("GenericData *")
"""Python-MIP constants""" from enum import Enum from cffi import FFI ffi = FFI() # epsilon number (practical zero) EPS = 10e-64 # infinity representation INF = float("inf") INT_MAX = 2**(ffi.sizeof("int") * 8 - 2) # constraint senses EQUAL = "=" LESS_OR_EQUAL = "<" GREATER_OR_EQUAL = ">" # optimization directions MIN = "MIN" MAX = "MAX" MINIMIZE = "MIN" MAXIMIZE = "MAX" # solvers CBC = "CBC" CPX = "CPX" # we plan to support CPLEX in the future CPLEX = "CPX" # we plan to support CPLEX in the future GRB = "GRB" GUROBI = "GRB"
int32_t ssi_int; /* Integer sent by sigqueue(3) */ uint64_t ssi_ptr; /* Pointer sent by sigqueue(3) */ uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */ uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */ uint64_t ssi_addr; /* Address that generated signal (for hardware-generated signals) */ ...; // uint8_t __pad[48]; /* Pad size to 128 bytes (allow for additional fields in the future) */ }; """) ffi.cdef(""" typedef struct { unsigned long int __val[%d]; } sigset_t; int signalfd(int fd, const sigset_t *mask, int flags); """ % (1024 / 8 * ffi.sizeof('unsigned long int'))) ffi.cdef(""" int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum); """) ffi.cdef(""" #define SIG_BLOCK ... #define SIG_UNBLOCK ... #define SIG_SETMASK ... int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset); int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);