1import os, sys, math, py 2from cffi import FFI, FFIError, VerificationError, VerificationMissing, model 3from cffi import CDefError 4from cffi import recompiler 5from testing.support import * 6from testing.support import _verify 7import _cffi_backend 8 9lib_m = ['m'] 10if sys.platform == 'win32': 11 #there is a small chance this fails on Mingw via environ $CC 12 import distutils.ccompiler 13 if distutils.ccompiler.get_default_compiler() == 'msvc': 14 lib_m = ['msvcrt'] 15 extra_compile_args = [] # no obvious -Werror equivalent on MSVC 16else: 17 if (sys.platform == 'darwin' and 18 [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): 19 # assume a standard clang or gcc 20 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion'] 21 # special things for clang 22 extra_compile_args.append('-Qunused-arguments') 23 else: 24 # assume a standard gcc 25 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion'] 26 27class FFI(FFI): 28 error = _cffi_backend.FFI.error 29 _extra_compile_args = extra_compile_args 30 _verify_counter = 0 31 32 def verify(self, preamble='', *args, **kwds): 33 # HACK to reuse the tests from ../cffi0/test_verify.py 34 FFI._verify_counter += 1 35 module_name = 'verify%d' % FFI._verify_counter 36 try: 37 del self._assigned_source 38 except AttributeError: 39 pass 40 self.set_source(module_name, preamble) 41 return _verify(self, module_name, preamble, *args, 42 extra_compile_args=self._extra_compile_args, **kwds) 43 44class FFI_warnings_not_error(FFI): 45 _extra_compile_args = [] 46 47 48def test_missing_function(ffi=None): 49 # uses the FFI hacked above with '-Werror' 50 if ffi is None: 51 ffi = FFI() 52 ffi.cdef("void some_completely_unknown_function();") 53 try: 54 lib = ffi.verify() 55 except (VerificationError, OSError, ImportError): 56 pass # expected case: we get a VerificationError 57 else: 58 # but depending on compiler and loader details, maybe 59 # 'lib' could actually be imported but will fail if we 60 # actually try to call the unknown function... Hard 61 # to test anything more. 62 pass 63 64def test_missing_function_import_error(): 65 # uses the original FFI that just gives a warning during compilation 66 test_missing_function(ffi=FFI_warnings_not_error()) 67 68def test_simple_case(): 69 ffi = FFI() 70 ffi.cdef("double sin(double x);") 71 lib = ffi.verify('#include <math.h>', libraries=lib_m) 72 assert lib.sin(1.23) == math.sin(1.23) 73 74def _Wconversion(cdef, source, **kargs): 75 if sys.platform in ('win32', 'darwin'): 76 py.test.skip("needs GCC") 77 ffi = FFI() 78 ffi.cdef(cdef) 79 py.test.raises(VerificationError, ffi.verify, source, **kargs) 80 extra_compile_args_orig = extra_compile_args[:] 81 extra_compile_args.remove('-Wconversion') 82 try: 83 lib = ffi.verify(source, **kargs) 84 finally: 85 extra_compile_args[:] = extra_compile_args_orig 86 return lib 87 88def test_Wconversion_unsigned(): 89 _Wconversion("unsigned foo(void);", 90 "int foo(void) { return -1;}") 91 92def test_Wconversion_integer(): 93 _Wconversion("short foo(void);", 94 "long long foo(void) { return 1<<sizeof(short);}") 95 96def test_Wconversion_floating(): 97 lib = _Wconversion("float sin(double);", 98 "#include <math.h>", libraries=lib_m) 99 res = lib.sin(1.23) 100 assert res != math.sin(1.23) # not exact, because of double->float 101 assert abs(res - math.sin(1.23)) < 1E-5 102 103def test_Wconversion_float2int(): 104 _Wconversion("int sinf(float);", 105 "#include <math.h>", libraries=lib_m) 106 107def test_Wconversion_double2int(): 108 _Wconversion("int sin(double);", 109 "#include <math.h>", libraries=lib_m) 110 111def test_rounding_1(): 112 ffi = FFI() 113 ffi.cdef("double sinf(float x);") 114 lib = ffi.verify('#include <math.h>', libraries=lib_m) 115 res = lib.sinf(1.23) 116 assert res != math.sin(1.23) # not exact, because of double->float 117 assert abs(res - math.sin(1.23)) < 1E-5 118 119def test_rounding_2(): 120 ffi = FFI() 121 ffi.cdef("double sin(float x);") 122 lib = ffi.verify('#include <math.h>', libraries=lib_m) 123 res = lib.sin(1.23) 124 assert res != math.sin(1.23) # not exact, because of double->float 125 assert abs(res - math.sin(1.23)) < 1E-5 126 127def test_strlen_exact(): 128 ffi = FFI() 129 ffi.cdef("size_t strlen(const char *s);") 130 lib = ffi.verify("#include <string.h>") 131 assert lib.strlen(b"hi there!") == 9 132 133def test_strlen_approximate(): 134 lib = _Wconversion("int strlen(char *s);", 135 "#include <string.h>") 136 assert lib.strlen(b"hi there!") == 9 137 138def test_return_approximate(): 139 for typename in ['short', 'int', 'long', 'long long']: 140 ffi = FFI() 141 ffi.cdef("%s foo(signed char x);" % typename) 142 lib = ffi.verify("signed char foo(signed char x) { return x;}") 143 assert lib.foo(-128) == -128 144 assert lib.foo(+127) == +127 145 146def test_strlen_array_of_char(): 147 ffi = FFI() 148 ffi.cdef("size_t strlen(char[]);") 149 lib = ffi.verify("#include <string.h>") 150 assert lib.strlen(b"hello") == 5 151 152def test_longdouble(): 153 ffi = FFI() 154 ffi.cdef("long double sinl(long double x);") 155 lib = ffi.verify('#include <math.h>', libraries=lib_m) 156 for input in [1.23, 157 ffi.cast("double", 1.23), 158 ffi.cast("long double", 1.23)]: 159 x = lib.sinl(input) 160 assert repr(x).startswith("<cdata 'long double'") 161 assert (float(x) - math.sin(1.23)) < 1E-10 162 163def test_longdouble_precision(): 164 # Test that we don't loose any precision of 'long double' when 165 # passing through Python and CFFI. 166 ffi = FFI() 167 ffi.cdef("long double step1(long double x);") 168 SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double") 169 lib = ffi.verify(""" 170 long double step1(long double x) 171 { 172 return 4*x-x*x; 173 } 174 """) 175 def do(cast_to_double): 176 x = 0.9789 177 for i in range(10000): 178 x = lib.step1(x) 179 if cast_to_double: 180 x = float(x) 181 return float(x) 182 183 more_precise = do(False) 184 less_precise = do(True) 185 if SAME_SIZE: 186 assert more_precise == less_precise 187 else: 188 assert abs(more_precise - less_precise) > 0.1 189 # Check the particular results on Intel 190 import platform 191 if (platform.machine().startswith('i386') or 192 platform.machine().startswith('i486') or 193 platform.machine().startswith('i586') or 194 platform.machine().startswith('i686') or 195 platform.machine().startswith('x86')): 196 assert abs(more_precise - 0.656769) < 0.001 197 assert abs(less_precise - 3.99091) < 0.001 198 else: 199 py.test.skip("don't know the very exact precision of 'long double'") 200 201 202all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES 203if sys.platform == 'win32': 204 all_primitive_types = all_primitive_types.copy() 205 del all_primitive_types['ssize_t'] 206all_integer_types = sorted(tp for tp in all_primitive_types 207 if all_primitive_types[tp] == 'i') 208all_float_types = sorted(tp for tp in all_primitive_types 209 if all_primitive_types[tp] == 'f') 210 211def all_signed_integer_types(ffi): 212 return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0] 213 214def all_unsigned_integer_types(ffi): 215 return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0] 216 217 218def test_primitive_category(): 219 for typename in all_primitive_types: 220 tp = model.PrimitiveType(typename) 221 C = tp.is_char_type() 222 F = tp.is_float_type() 223 X = tp.is_complex_type() 224 I = tp.is_integer_type() 225 assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t')) 226 assert F == (typename in ('float', 'double', 'long double')) 227 assert X == (typename in ('float _Complex', 'double _Complex')) 228 assert I + F + C + X == 1 # one and only one of them is true 229 230def test_all_integer_and_float_types(): 231 typenames = [] 232 for typename in all_primitive_types: 233 if (all_primitive_types[typename] == 'c' or 234 all_primitive_types[typename] == 'j' or # complex 235 typename == '_Bool' or typename == 'long double'): 236 pass 237 else: 238 typenames.append(typename) 239 # 240 ffi = FFI() 241 ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp) 242 for tp in typenames])) 243 lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" % 244 (tp, tp.replace(' ', '_'), tp, tp) 245 for tp in typenames])) 246 for typename in typenames: 247 foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_')) 248 assert foo(42) == 43 249 if sys.version < '3': 250 assert foo(long(44)) == 45 251 assert foo(ffi.cast(typename, 46)) == 47 252 py.test.raises(TypeError, foo, ffi.NULL) 253 # 254 # check for overflow cases 255 if all_primitive_types[typename] == 'f': 256 continue 257 for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1, 258 2**5, 2**10, 2**20, 2**40, 2**80]: 259 overflows = int(ffi.cast(typename, value)) != value 260 if overflows: 261 py.test.raises(OverflowError, foo, value) 262 else: 263 assert foo(value) == value + 1 264 265def test_var_signed_integer_types(): 266 ffi = FFI() 267 lst = all_signed_integer_types(ffi) 268 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) 269 for tp in lst]) 270 ffi.cdef(csource) 271 lib = ffi.verify(csource) 272 for tp in lst: 273 varname = 'somevar_%s' % tp.replace(' ', '_') 274 sz = ffi.sizeof(tp) 275 max = (1 << (8*sz-1)) - 1 276 min = -(1 << (8*sz-1)) 277 setattr(lib, varname, max) 278 assert getattr(lib, varname) == max 279 setattr(lib, varname, min) 280 assert getattr(lib, varname) == min 281 py.test.raises(OverflowError, setattr, lib, varname, max+1) 282 py.test.raises(OverflowError, setattr, lib, varname, min-1) 283 284def test_var_unsigned_integer_types(): 285 ffi = FFI() 286 lst = all_unsigned_integer_types(ffi) 287 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) 288 for tp in lst]) 289 ffi.cdef(csource) 290 lib = ffi.verify(csource) 291 for tp in lst: 292 varname = 'somevar_%s' % tp.replace(' ', '_') 293 sz = ffi.sizeof(tp) 294 if tp != '_Bool': 295 max = (1 << (8*sz)) - 1 296 else: 297 max = 1 298 setattr(lib, varname, max) 299 assert getattr(lib, varname) == max 300 setattr(lib, varname, 0) 301 assert getattr(lib, varname) == 0 302 py.test.raises(OverflowError, setattr, lib, varname, max+1) 303 py.test.raises(OverflowError, setattr, lib, varname, -1) 304 305def test_fn_signed_integer_types(): 306 ffi = FFI() 307 lst = all_signed_integer_types(ffi) 308 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp) 309 for tp in lst]) 310 ffi.cdef(cdefsrc) 311 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" % 312 (tp, tp.replace(' ', '_'), tp) for tp in lst]) 313 lib = ffi.verify(verifysrc) 314 for tp in lst: 315 fnname = 'somefn_%s' % tp.replace(' ', '_') 316 sz = ffi.sizeof(tp) 317 max = (1 << (8*sz-1)) - 1 318 min = -(1 << (8*sz-1)) 319 fn = getattr(lib, fnname) 320 assert fn(max) == max 321 assert fn(min) == min 322 py.test.raises(OverflowError, fn, max + 1) 323 py.test.raises(OverflowError, fn, min - 1) 324 325def test_fn_unsigned_integer_types(): 326 ffi = FFI() 327 lst = all_unsigned_integer_types(ffi) 328 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp) 329 for tp in lst]) 330 ffi.cdef(cdefsrc) 331 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" % 332 (tp, tp.replace(' ', '_'), tp) for tp in lst]) 333 lib = ffi.verify(verifysrc) 334 for tp in lst: 335 fnname = 'somefn_%s' % tp.replace(' ', '_') 336 sz = ffi.sizeof(tp) 337 if tp != '_Bool': 338 max = (1 << (8*sz)) - 1 339 else: 340 max = 1 341 fn = getattr(lib, fnname) 342 assert fn(max) == max 343 assert fn(0) == 0 344 py.test.raises(OverflowError, fn, max + 1) 345 py.test.raises(OverflowError, fn, -1) 346 347def test_char_type(): 348 ffi = FFI() 349 ffi.cdef("char foo(char);") 350 lib = ffi.verify("char foo(char x) { return ++x; }") 351 assert lib.foo(b"A") == b"B" 352 py.test.raises(TypeError, lib.foo, b"bar") 353 py.test.raises(TypeError, lib.foo, "bar") 354 355def test_wchar_type(): 356 ffi = FFI() 357 if ffi.sizeof('wchar_t') == 2: 358 uniexample1 = u+'\u1234' 359 uniexample2 = u+'\u1235' 360 else: 361 uniexample1 = u+'\U00012345' 362 uniexample2 = u+'\U00012346' 363 # 364 ffi.cdef("wchar_t foo(wchar_t);") 365 lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }") 366 assert lib.foo(uniexample1) == uniexample2 367 368def test_no_argument(): 369 ffi = FFI() 370 ffi.cdef("int foo(void);") 371 lib = ffi.verify("int foo(void) { return 42; }") 372 assert lib.foo() == 42 373 374def test_two_arguments(): 375 ffi = FFI() 376 ffi.cdef("int foo(int, int);") 377 lib = ffi.verify("int foo(int a, int b) { return a - b; }") 378 assert lib.foo(40, -2) == 42 379 380def test_macro(): 381 ffi = FFI() 382 ffi.cdef("int foo(int, int);") 383 lib = ffi.verify("#define foo(a, b) ((a) * (b))") 384 assert lib.foo(-6, -7) == 42 385 386def test_ptr(): 387 ffi = FFI() 388 ffi.cdef("int *foo(int *);") 389 lib = ffi.verify("int *foo(int *a) { return a; }") 390 assert lib.foo(ffi.NULL) == ffi.NULL 391 p = ffi.new("int *", 42) 392 q = ffi.new("int *", 42) 393 assert lib.foo(p) == p 394 assert lib.foo(q) != p 395 396def test_bogus_ptr(): 397 ffi = FFI() 398 ffi.cdef("int *foo(int *);") 399 lib = ffi.verify("int *foo(int *a) { return a; }") 400 py.test.raises(TypeError, lib.foo, ffi.new("short *", 42)) 401 402 403def test_verify_typedefs(): 404 py.test.skip("ignored so far") 405 types = ['signed char', 'unsigned char', 'int', 'long'] 406 for cdefed in types: 407 for real in types: 408 ffi = FFI() 409 ffi.cdef("typedef %s foo_t;" % cdefed) 410 if cdefed == real: 411 ffi.verify("typedef %s foo_t;" % real) 412 else: 413 py.test.raises(VerificationError, ffi.verify, 414 "typedef %s foo_t;" % real) 415 416def test_nondecl_struct(): 417 ffi = FFI() 418 ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);") 419 lib = ffi.verify("typedef struct foo_s foo_t;\n" 420 "int bar(foo_t *f) { (void)f; return 42; }\n") 421 assert lib.bar(ffi.NULL) == 42 422 423def test_ffi_full_struct(): 424 def check(verified_code): 425 ffi = FFI() 426 ffi.cdef("struct foo_s { char x; int y; long *z; };") 427 ffi.verify(verified_code) 428 ffi.new("struct foo_s *", {}) 429 430 check("struct foo_s { char x; int y; long *z; };") 431 # 432 if sys.platform != 'win32': # XXX fixme: only gives warnings 433 py.test.raises(VerificationError, check, 434 "struct foo_s { char x; int y; int *z; };") 435 # 436 py.test.raises(VerificationError, check, 437 "struct foo_s { int y; long *z; };") # cdef'ed field x is missing 438 # 439 e = py.test.raises(FFI.error, check, 440 "struct foo_s { int y; char x; long *z; };") 441 assert str(e.value).startswith( 442 "struct foo_s: wrong offset for field 'x'" 443 " (cdef says 0, but C compiler says 4)") 444 # 445 e = py.test.raises(FFI.error, check, 446 "struct foo_s { char x; int y; long *z; char extra; };") 447 assert str(e.value).startswith( 448 "struct foo_s: wrong total size" 449 " (cdef says %d, but C compiler says %d)" % ( 450 8 + FFI().sizeof('long *'), 451 8 + FFI().sizeof('long *') * 2)) 452 # 453 # a corner case that we cannot really detect, but where it has no 454 # bad consequences: the size is the same, but there is an extra field 455 # that replaces what is just padding in our declaration above 456 check("struct foo_s { char x, extra; int y; long *z; };") 457 # 458 e = py.test.raises(FFI.error, check, 459 "struct foo_s { char x; short pad; short y; long *z; };") 460 assert str(e.value).startswith( 461 "struct foo_s: wrong size for field 'y'" 462 " (cdef says 4, but C compiler says 2)") 463 464def test_ffi_nonfull_struct(): 465 ffi = FFI() 466 ffi.cdef(""" 467 struct foo_s { 468 int x; 469 ...; 470 }; 471 """) 472 py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s') 473 py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x') 474 py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *') 475 ffi.verify(""" 476 struct foo_s { 477 int a, b, x, c, d, e; 478 }; 479 """) 480 assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int') 481 assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int') 482 483def test_ffi_nonfull_alignment(): 484 ffi = FFI() 485 ffi.cdef("struct foo_s { char x; ...; };") 486 ffi.verify("struct foo_s { int a, b; char x; };") 487 assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int') 488 assert ffi.alignof('struct foo_s') == ffi.sizeof('int') 489 490def _check_field_match(typename, real, expect_mismatch): 491 ffi = FFI() 492 testing_by_size = (expect_mismatch == 'by_size') 493 if testing_by_size: 494 expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real) 495 ffi.cdef("struct foo_s { %s x; ...; };" % typename) 496 try: 497 ffi.verify("struct foo_s { %s x; };" % real) 498 ffi.new("struct foo_s *", []) # because some mismatches show up lazily 499 except (VerificationError, ffi.error): 500 if not expect_mismatch: 501 if testing_by_size and typename != real: 502 print("ignoring mismatch between %s* and %s* even though " 503 "they have the same size" % (typename, real)) 504 return 505 raise AssertionError("unexpected mismatch: %s should be accepted " 506 "as equal to %s" % (typename, real)) 507 else: 508 if expect_mismatch: 509 raise AssertionError("mismatch not detected: " 510 "%s != %s" % (typename, real)) 511 512def test_struct_bad_sized_integer(): 513 for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']: 514 for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']: 515 _check_field_match(typename, real, "by_size") 516 517def test_struct_bad_sized_float(): 518 for typename in all_float_types: 519 for real in all_float_types: 520 _check_field_match(typename, real, "by_size") 521 522def test_struct_signedness_ignored(): 523 _check_field_match("int", "unsigned int", expect_mismatch=False) 524 _check_field_match("unsigned short", "signed short", expect_mismatch=False) 525 526def test_struct_float_vs_int(): 527 if sys.platform == 'win32': 528 py.test.skip("XXX fixme: only gives warnings") 529 ffi = FFI() 530 for typename in all_signed_integer_types(ffi): 531 for real in all_float_types: 532 _check_field_match(typename, real, expect_mismatch=True) 533 for typename in all_float_types: 534 for real in all_signed_integer_types(ffi): 535 _check_field_match(typename, real, expect_mismatch=True) 536 537def test_struct_array_field(): 538 ffi = FFI() 539 ffi.cdef("struct foo_s { int a[17]; ...; };") 540 ffi.verify("struct foo_s { int x; int a[17]; int y; };") 541 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') 542 s = ffi.new("struct foo_s *") 543 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int') 544 545def test_struct_array_no_length(): 546 ffi = FFI() 547 ffi.cdef("struct foo_s { int a[]; int y; ...; };\n" 548 "int bar(struct foo_s *);\n") 549 lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n" 550 "int bar(struct foo_s *f) { return f->a[14]; }\n") 551 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') 552 s = ffi.new("struct foo_s *") 553 assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length 554 assert len(s.a) == 18 # max length, computed from the size and start offset 555 s.a[14] = 4242 556 assert lib.bar(s) == 4242 557 # with no declared length, out-of-bound accesses are not detected 558 s.a[17] = -521 559 assert s.y == s.a[17] == -521 560 # 561 s = ffi.new("struct foo_s *", {'a': list(range(17))}) 562 assert s.a[16] == 16 563 # overflows at construction time not detected either 564 s = ffi.new("struct foo_s *", {'a': list(range(18))}) 565 assert s.y == s.a[17] == 17 566 567def test_struct_array_guess_length(): 568 ffi = FFI() 569 ffi.cdef("struct foo_s { int a[...]; };") 570 ffi.verify("struct foo_s { int x; int a[17]; int y; };") 571 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') 572 s = ffi.new("struct foo_s *") 573 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int') 574 py.test.raises(IndexError, 's.a[17]') 575 576def test_struct_array_c99_1(): 577 if sys.platform == 'win32': 578 py.test.skip("requires C99") 579 ffi = FFI() 580 ffi.cdef("struct foo_s { int x; int a[]; };") 581 ffi.verify("struct foo_s { int x; int a[]; };") 582 assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int') 583 s = ffi.new("struct foo_s *", [424242, 4]) 584 assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int') 585 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int') 586 # ^^^ explanation: if you write in C: "char x[5];", then 587 # "sizeof(x)" will evaluate to 5. The behavior above is 588 # a generalization of that to "struct foo_s[len(a)=5] x;" 589 # if you could do that in C. 590 assert s.a[3] == 0 591 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) 592 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int') 593 assert s.a[3] == -10 594 s = ffi.new("struct foo_s *") 595 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') 596 s = ffi.new("struct foo_s *", [424242]) 597 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') 598 599def test_struct_array_c99_2(): 600 if sys.platform == 'win32': 601 py.test.skip("requires C99") 602 ffi = FFI() 603 ffi.cdef("struct foo_s { int x; int a[]; ...; };") 604 ffi.verify("struct foo_s { int x, y; int a[]; };") 605 assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int') 606 s = ffi.new("struct foo_s *", [424242, 4]) 607 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int') 608 assert s.a[3] == 0 609 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) 610 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int') 611 assert s.a[3] == -10 612 s = ffi.new("struct foo_s *") 613 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') 614 s = ffi.new("struct foo_s *", [424242]) 615 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') 616 617def test_struct_ptr_to_array_field(): 618 ffi = FFI() 619 ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };") 620 ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n" 621 "struct bar_s { int x; int *a; int y; };") 622 assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s") 623 s = ffi.new("struct foo_s *") 624 assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *") 625 626def test_struct_with_bitfield_exact(): 627 ffi = FFI() 628 ffi.cdef("struct foo_s { int a:2, b:3; };") 629 ffi.verify("struct foo_s { int a:2, b:3; };") 630 s = ffi.new("struct foo_s *") 631 s.b = 3 632 py.test.raises(OverflowError, "s.b = 4") 633 assert s.b == 3 634 635def test_struct_with_bitfield_enum(): 636 ffi = FFI() 637 code = """ 638 typedef enum { AA, BB, CC } foo_e; 639 typedef struct { foo_e f:2; } foo_s; 640 """ 641 ffi.cdef(code) 642 ffi.verify(code) 643 s = ffi.new("foo_s *") 644 s.f = 1 645 assert s.f == 1 646 if int(ffi.cast("foo_e", -1)) < 0: 647 two = -2 648 else: 649 two = 2 650 s.f = two 651 assert s.f == two 652 653def test_unsupported_struct_with_bitfield_ellipsis(): 654 ffi = FFI() 655 py.test.raises(NotImplementedError, ffi.cdef, 656 "struct foo_s { int a:2, b:3; ...; };") 657 658def test_global_constants(): 659 ffi = FFI() 660 # use 'static const int', as generally documented, although in this 661 # case the 'static' is completely ignored. 662 ffi.cdef("static const int AA, BB, CC, DD;") 663 lib = ffi.verify("#define AA 42\n" 664 "#define BB (-43) // blah\n" 665 "#define CC (22*2) /* foobar */\n" 666 "#define DD ((unsigned int)142) /* foo\nbar */\n") 667 assert lib.AA == 42 668 assert lib.BB == -43 669 assert lib.CC == 44 670 assert lib.DD == 142 671 672def test_global_const_int_size(): 673 # integer constants: ignore the declared type, always just use the value 674 for value in [-2**63, -2**31, -2**15, 675 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32, 676 2**63-1, 2**63, 2**64-1]: 677 ffi = FFI() 678 if value == int(ffi.cast("long long", value)): 679 if value < 0: 680 vstr = '(-%dLL-1)' % (~value,) 681 else: 682 vstr = '%dLL' % value 683 elif value == int(ffi.cast("unsigned long long", value)): 684 vstr = '%dULL' % value 685 else: 686 raise AssertionError(value) 687 ffi.cdef("static const unsigned short AA;") 688 lib = ffi.verify("#define AA %s\n" % vstr) 689 assert lib.AA == value 690 assert type(lib.AA) is type(int(lib.AA)) 691 692def test_global_constants_non_int(): 693 ffi = FFI() 694 ffi.cdef("static char *const PP;") 695 lib = ffi.verify('static char *const PP = "testing!";\n') 696 assert ffi.typeof(lib.PP) == ffi.typeof("char *") 697 assert ffi.string(lib.PP) == b"testing!" 698 699def test_nonfull_enum(): 700 ffi = FFI() 701 ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };") 702 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2') 703 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") 704 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2" 705 assert ffi.string(ffi.cast('enum ee', -10)) == "EE3" 706 # 707 assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10} 708 assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'} 709 710def test_full_enum(): 711 ffi = FFI() 712 ffi.cdef("enum ee { EE1, EE2, EE3 };") 713 lib = ffi.verify("enum ee { EE1, EE2, EE3 };") 714 assert [lib.EE1, lib.EE2, lib.EE3] == [0, 1, 2] 715 716def test_enum_usage(): 717 ffi = FFI() 718 ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;") 719 lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;") 720 assert lib.EE2 == 1 721 s = ffi.new("sp", [lib.EE2]) 722 assert s.x == 1 723 s.x = 17 724 assert s.x == 17 725 726def test_anonymous_enum(): 727 ffi = FFI() 728 ffi.cdef("enum { EE1 }; enum { EE2, EE3 };") 729 lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };") 730 assert lib.EE1 == 0 731 assert lib.EE2 == 0 732 assert lib.EE3 == 1 733 734def test_nonfull_anonymous_enum(): 735 ffi = FFI() 736 ffi.cdef("enum { EE1, ... }; enum { EE3, ... };") 737 lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };") 738 assert lib.EE1 == 1 739 assert lib.EE3 == 0 740 741def test_nonfull_enum_syntax2(): 742 ffi = FFI() 743 ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };") 744 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1') 745 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") 746 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2' 747 assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3' 748 # 749 ffi = FFI() 750 ffi.cdef("enum ee { EE1, EE2=\t... };") 751 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1') 752 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") 753 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2' 754 # 755 ffi = FFI() 756 ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };") 757 ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ") 758 assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4' 759 assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5' 760 761def test_get_set_errno(): 762 ffi = FFI() 763 ffi.cdef("int foo(int);") 764 lib = ffi.verify(""" 765 static int foo(int x) 766 { 767 errno += 1; 768 return x * 7; 769 } 770 """) 771 ffi.errno = 15 772 assert lib.foo(6) == 42 773 assert ffi.errno == 16 774 775def test_define_int(): 776 ffi = FFI() 777 ffi.cdef("#define FOO ...\n" 778 "\t#\tdefine\tBAR\t...\t\n" 779 "#define BAZ ...\n") 780 lib = ffi.verify("#define FOO 42\n" 781 "#define BAR (-44)\n" 782 "#define BAZ 0xffffffffffffffffULL\n") 783 assert lib.FOO == 42 784 assert lib.BAR == -44 785 assert lib.BAZ == 0xffffffffffffffff 786 787def test_access_variable(): 788 ffi = FFI() 789 ffi.cdef("int foo(void);\n" 790 "int somenumber;") 791 lib = ffi.verify(""" 792 static int somenumber = 2; 793 static int foo(void) { 794 return somenumber * 7; 795 } 796 """) 797 assert lib.somenumber == 2 798 assert lib.foo() == 14 799 lib.somenumber = -6 800 assert lib.foo() == -42 801 assert lib.somenumber == -6 802 lib.somenumber = 2 # reset for the next run, if any 803 804def test_access_address_of_variable(): 805 # access the address of 'somenumber': need a trick 806 ffi = FFI() 807 ffi.cdef("int somenumber; static int *const somenumberptr;") 808 lib = ffi.verify(""" 809 static int somenumber = 2; 810 #define somenumberptr (&somenumber) 811 """) 812 assert lib.somenumber == 2 813 lib.somenumberptr[0] = 42 814 assert lib.somenumber == 42 815 lib.somenumber = 2 # reset for the next run, if any 816 817def test_access_array_variable(length=5): 818 ffi = FFI() 819 ffi.cdef("int foo(int);\n" 820 "int somenumber[%s];" % (length,)) 821 lib = ffi.verify(""" 822 static int somenumber[] = {2, 2, 3, 4, 5}; 823 static int foo(int i) { 824 return somenumber[i] * 7; 825 } 826 """) 827 if length == '': 828 # a global variable of an unknown array length is implicitly 829 # transformed into a global pointer variable, because we can only 830 # work with array instances whose length we know. using a pointer 831 # instead of an array gives the correct effects. 832 assert repr(lib.somenumber).startswith("<cdata 'int *' 0x") 833 py.test.raises(TypeError, len, lib.somenumber) 834 else: 835 assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length) 836 assert len(lib.somenumber) == 5 837 assert lib.somenumber[3] == 4 838 assert lib.foo(3) == 28 839 lib.somenumber[3] = -6 840 assert lib.foo(3) == -42 841 assert lib.somenumber[3] == -6 842 assert lib.somenumber[4] == 5 843 lib.somenumber[3] = 4 # reset for the next run, if any 844 845def test_access_array_variable_length_hidden(): 846 test_access_array_variable(length='') 847 848def test_access_struct_variable(): 849 ffi = FFI() 850 ffi.cdef("struct foo { int x; ...; };\n" 851 "int foo(int);\n" 852 "struct foo stuff;") 853 lib = ffi.verify(""" 854 struct foo { int x, y, z; }; 855 static struct foo stuff = {2, 5, 8}; 856 static int foo(int i) { 857 switch (i) { 858 case 0: return stuff.x * 7; 859 case 1: return stuff.y * 7; 860 case 2: return stuff.z * 7; 861 } 862 return -1; 863 } 864 """) 865 assert lib.stuff.x == 2 866 assert lib.foo(0) == 14 867 assert lib.foo(1) == 35 868 assert lib.foo(2) == 56 869 lib.stuff.x = -6 870 assert lib.foo(0) == -42 871 assert lib.foo(1) == 35 872 lib.stuff.x = 2 # reset for the next run, if any 873 874def test_access_callback(): 875 ffi = FFI() 876 ffi.cdef("int (*cb)(int);\n" 877 "int foo(int);\n" 878 "void reset_cb(void);") 879 lib = ffi.verify(""" 880 static int g(int x) { return x * 7; } 881 static int (*cb)(int); 882 static int foo(int i) { return cb(i) - 1; } 883 static void reset_cb(void) { cb = g; } 884 """) 885 lib.reset_cb() 886 assert lib.foo(6) == 41 887 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222) 888 lib.cb = my_callback 889 assert lib.foo(4) == 887 890 891def test_access_callback_function_typedef(): 892 ffi = FFI() 893 ffi.cdef("typedef int mycallback_t(int);\n" 894 "mycallback_t *cb;\n" 895 "int foo(int);\n" 896 "void reset_cb(void);") 897 lib = ffi.verify(""" 898 static int g(int x) { return x * 7; } 899 static int (*cb)(int); 900 static int foo(int i) { return cb(i) - 1; } 901 static void reset_cb(void) { cb = g; } 902 """) 903 lib.reset_cb() 904 assert lib.foo(6) == 41 905 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222) 906 lib.cb = my_callback 907 assert lib.foo(4) == 887 908 909def test_call_with_struct_ptr(): 910 ffi = FFI() 911 ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);") 912 lib = ffi.verify(""" 913 typedef struct { int y, x; } foo_t; 914 static int foo(foo_t *f) { return f->x * 7; } 915 """) 916 f = ffi.new("foo_t *") 917 f.x = 6 918 assert lib.foo(f) == 42 919 920def test_unknown_type(): 921 ffi = FFI() 922 ffi.cdef(""" 923 typedef ... token_t; 924 int foo(token_t *); 925 #define TOKEN_SIZE ... 926 """) 927 lib = ffi.verify(""" 928 typedef float token_t; 929 static int foo(token_t *tk) { 930 if (!tk) 931 return -42; 932 *tk += 1.601f; 933 return (int)*tk; 934 } 935 #define TOKEN_SIZE sizeof(token_t) 936 """) 937 # we cannot let ffi.new("token_t *") work, because we don't know ahead of 938 # time if it's ok to ask 'sizeof(token_t)' in the C code or not. 939 # See test_unknown_type_2. Workaround. 940 tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized 941 tk = ffi.cast("token_t *", tkmem) 942 results = [lib.foo(tk) for i in range(6)] 943 assert results == [1, 3, 4, 6, 8, 9] 944 assert lib.foo(ffi.NULL) == -42 945 946def test_unknown_type_2(): 947 ffi = FFI() 948 ffi.cdef("typedef ... token_t;") 949 lib = ffi.verify("typedef struct token_s token_t;") 950 # assert did not crash, even though 'sizeof(token_t)' is not valid in C. 951 952def test_unknown_type_3(): 953 ffi = FFI() 954 ffi.cdef(""" 955 typedef ... *token_p; 956 token_p foo(token_p); 957 """) 958 lib = ffi.verify(""" 959 typedef struct _token_s *token_p; 960 token_p foo(token_p arg) { 961 if (arg) 962 return (token_p)0x12347; 963 else 964 return (token_p)0x12345; 965 } 966 """) 967 p = lib.foo(ffi.NULL) 968 assert int(ffi.cast("intptr_t", p)) == 0x12345 969 q = lib.foo(p) 970 assert int(ffi.cast("intptr_t", q)) == 0x12347 971 972def test_varargs(): 973 ffi = FFI() 974 ffi.cdef("int foo(int x, ...);") 975 lib = ffi.verify(""" 976 int foo(int x, ...) { 977 va_list vargs; 978 va_start(vargs, x); 979 x -= va_arg(vargs, int); 980 x -= va_arg(vargs, int); 981 va_end(vargs); 982 return x; 983 } 984 """) 985 assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42 986 987def test_varargs_exact(): 988 if sys.platform == 'win32': 989 py.test.skip("XXX fixme: only gives warnings") 990 ffi = FFI() 991 ffi.cdef("int foo(int x, ...);") 992 py.test.raises(VerificationError, ffi.verify, """ 993 int foo(long long x, ...) { 994 return x; 995 } 996 """) 997 998def test_varargs_struct(): 999 ffi = FFI() 1000 ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);") 1001 lib = ffi.verify(""" 1002 struct foo_s { 1003 char a; int b; 1004 }; 1005 int foo(int x, ...) { 1006 va_list vargs; 1007 struct foo_s s; 1008 va_start(vargs, x); 1009 s = va_arg(vargs, struct foo_s); 1010 va_end(vargs); 1011 return s.a - s.b; 1012 } 1013 """) 1014 s = ffi.new("struct foo_s *", [b'B', 1]) 1015 assert lib.foo(50, s[0]) == ord('A') 1016 1017def test_autofilled_struct_as_argument(): 1018 ffi = FFI() 1019 ffi.cdef("struct foo_s { long a; double b; ...; };\n" 1020 "int foo(struct foo_s);") 1021 lib = ffi.verify(""" 1022 struct foo_s { 1023 double b; 1024 long a; 1025 }; 1026 int foo(struct foo_s s) { 1027 return (int)s.a - (int)s.b; 1028 } 1029 """) 1030 s = ffi.new("struct foo_s *", [100, 1]) 1031 assert lib.foo(s[0]) == 99 1032 assert lib.foo([100, 1]) == 99 1033 1034def test_autofilled_struct_as_argument_dynamic(): 1035 ffi = FFI() 1036 ffi.cdef("struct foo_s { long a; ...; };\n" 1037 "int (*foo)(struct foo_s);") 1038 lib = ffi.verify(""" 1039 struct foo_s { 1040 double b; 1041 long a; 1042 }; 1043 int foo1(struct foo_s s) { 1044 return (int)s.a - (int)s.b; 1045 } 1046 int (*foo)(struct foo_s s) = &foo1; 1047 """) 1048 e = py.test.raises(NotImplementedError, lib.foo, "?") 1049 msg = ("ctype 'struct foo_s' not supported as argument. It is a struct " 1050 'declared with "...;", but the C calling convention may depend on ' 1051 "the missing fields; or, it contains anonymous struct/unions. " 1052 "Such structs are only supported as argument " 1053 "if the function is 'API mode' and non-variadic (i.e. declared " 1054 "inside ffibuilder.cdef()+ffibuilder.set_source() and not taking " 1055 "a final '...' argument)") 1056 assert str(e.value) == msg 1057 1058def test_func_returns_struct(): 1059 ffi = FFI() 1060 ffi.cdef(""" 1061 struct foo_s { int aa, bb; }; 1062 struct foo_s foo(int a, int b); 1063 """) 1064 lib = ffi.verify(""" 1065 struct foo_s { int aa, bb; }; 1066 struct foo_s foo(int a, int b) { 1067 struct foo_s r; 1068 r.aa = a*a; 1069 r.bb = b*b; 1070 return r; 1071 } 1072 """) 1073 s = lib.foo(6, 7) 1074 assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>" 1075 assert s.aa == 36 1076 assert s.bb == 49 1077 1078def test_func_as_funcptr(): 1079 ffi = FFI() 1080 ffi.cdef("int *(*const fooptr)(void);") 1081 lib = ffi.verify(""" 1082 int *foo(void) { 1083 return (int*)"foobar"; 1084 } 1085 int *(*fooptr)(void) = foo; 1086 """) 1087 foochar = ffi.cast("char *(*)(void)", lib.fooptr) 1088 s = foochar() 1089 assert ffi.string(s) == b"foobar" 1090 1091def test_funcptr_as_argument(): 1092 ffi = FFI() 1093 ffi.cdef(""" 1094 void qsort(void *base, size_t nel, size_t width, 1095 int (*compar)(const void *, const void *)); 1096 """) 1097 ffi.verify("#include <stdlib.h>") 1098 1099def test_func_as_argument(): 1100 ffi = FFI() 1101 ffi.cdef(""" 1102 void qsort(void *base, size_t nel, size_t width, 1103 int compar(const void *, const void *)); 1104 """) 1105 ffi.verify("#include <stdlib.h>") 1106 1107def test_array_as_argument(): 1108 ffi = FFI() 1109 ffi.cdef(""" 1110 size_t strlen(char string[]); 1111 """) 1112 ffi.verify("#include <string.h>") 1113 1114def test_enum_as_argument(): 1115 ffi = FFI() 1116 ffi.cdef(""" 1117 enum foo_e { AA, BB, ... }; 1118 int foo_func(enum foo_e); 1119 """) 1120 lib = ffi.verify(""" 1121 enum foo_e { AA, CC, BB }; 1122 int foo_func(enum foo_e e) { return (int)e; } 1123 """) 1124 assert lib.foo_func(lib.BB) == 2 1125 py.test.raises(TypeError, lib.foo_func, "BB") 1126 1127def test_enum_as_function_result(): 1128 ffi = FFI() 1129 ffi.cdef(""" 1130 enum foo_e { AA, BB, ... }; 1131 enum foo_e foo_func(int x); 1132 """) 1133 lib = ffi.verify(""" 1134 enum foo_e { AA, CC, BB }; 1135 enum foo_e foo_func(int x) { return (enum foo_e)x; } 1136 """) 1137 assert lib.foo_func(lib.BB) == lib.BB == 2 1138 1139def test_enum_values(): 1140 ffi = FFI() 1141 ffi.cdef("enum enum1_e { AA, BB };") 1142 lib = ffi.verify("enum enum1_e { AA, BB };") 1143 assert lib.AA == 0 1144 assert lib.BB == 1 1145 assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB' 1146 1147def test_typedef_complete_enum(): 1148 ffi = FFI() 1149 ffi.cdef("typedef enum { AA, BB } enum1_t;") 1150 lib = ffi.verify("typedef enum { AA, BB } enum1_t;") 1151 assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB' 1152 assert lib.AA == 0 1153 assert lib.BB == 1 1154 1155def test_typedef_broken_complete_enum(): 1156 # xxx this is broken in old cffis, but works with recompiler.py 1157 ffi = FFI() 1158 ffi.cdef("typedef enum { AA, BB } enum1_t;") 1159 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;") 1160 assert lib.AA == 0 1161 assert lib.BB == 2 1162 1163def test_typedef_incomplete_enum(): 1164 ffi = FFI() 1165 ffi.cdef("typedef enum { AA, BB, ... } enum1_t;") 1166 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;") 1167 assert ffi.string(ffi.cast("enum1_t", 1)) == '1' 1168 assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB' 1169 assert lib.AA == 0 1170 assert lib.BB == 2 1171 1172def test_typedef_enum_as_argument(): 1173 ffi = FFI() 1174 ffi.cdef(""" 1175 typedef enum { AA, BB, ... } foo_t; 1176 int foo_func(foo_t); 1177 """) 1178 lib = ffi.verify(""" 1179 typedef enum { AA, CC, BB } foo_t; 1180 int foo_func(foo_t e) { return (int)e; } 1181 """) 1182 assert lib.foo_func(lib.BB) == lib.BB == 2 1183 py.test.raises(TypeError, lib.foo_func, "BB") 1184 1185def test_typedef_enum_as_function_result(): 1186 ffi = FFI() 1187 ffi.cdef(""" 1188 typedef enum { AA, BB, ... } foo_t; 1189 foo_t foo_func(int x); 1190 """) 1191 lib = ffi.verify(""" 1192 typedef enum { AA, CC, BB } foo_t; 1193 foo_t foo_func(int x) { return (foo_t)x; } 1194 """) 1195 assert lib.foo_func(lib.BB) == lib.BB == 2 1196 1197def test_function_typedef(): 1198 ffi = FFI() 1199 ffi.cdef(""" 1200 typedef double func_t(double); 1201 func_t sin; 1202 """) 1203 lib = ffi.verify('#include <math.h>', libraries=lib_m) 1204 assert lib.sin(1.23) == math.sin(1.23) 1205 1206def test_opaque_integer_as_function_result(): 1207 #import platform 1208 #if platform.machine().startswith('sparc'): 1209 # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)') 1210 #elif platform.machine() == 'mips64' and sys.maxsize > 2**32: 1211 # py.test.skip('Segfaults on mips64el') 1212 # XXX bad abuse of "struct { ...; }". It only works a bit by chance 1213 # anyway. XXX think about something better :-( 1214 ffi = FFI() 1215 ffi.cdef(""" 1216 typedef struct { ...; } myhandle_t; 1217 myhandle_t foo(void); 1218 """) 1219 lib = ffi.verify(""" 1220 typedef short myhandle_t; 1221 myhandle_t foo(void) { return 42; } 1222 """) 1223 h = lib.foo() 1224 assert ffi.sizeof(h) == ffi.sizeof("short") 1225 1226def test_return_partial_struct(): 1227 ffi = FFI() 1228 ffi.cdef(""" 1229 typedef struct { int x; ...; } foo_t; 1230 foo_t foo(void); 1231 """) 1232 lib = ffi.verify(""" 1233 typedef struct { int y, x; } foo_t; 1234 foo_t foo(void) { foo_t r = { 45, 81 }; return r; } 1235 """) 1236 h = lib.foo() 1237 assert ffi.sizeof(h) == 2 * ffi.sizeof("int") 1238 assert h.x == 81 1239 1240def test_take_and_return_partial_structs(): 1241 ffi = FFI() 1242 ffi.cdef(""" 1243 typedef struct { int x; ...; } foo_t; 1244 foo_t foo(foo_t, foo_t); 1245 """) 1246 lib = ffi.verify(""" 1247 typedef struct { int y, x; } foo_t; 1248 foo_t foo(foo_t a, foo_t b) { 1249 foo_t r = { 100, a.x * 5 + b.x * 7 }; 1250 return r; 1251 } 1252 """) 1253 args = ffi.new("foo_t[3]") 1254 args[0].x = 1000 1255 args[2].x = -498 1256 h = lib.foo(args[0], args[2]) 1257 assert ffi.sizeof(h) == 2 * ffi.sizeof("int") 1258 assert h.x == 1000 * 5 - 498 * 7 1259 1260def test_cannot_name_struct_type(): 1261 ffi = FFI() 1262 ffi.cdef("typedef struct { int x; } **sp; void foo(sp);") 1263 e = py.test.raises(VerificationError, ffi.verify, 1264 "typedef struct { int x; } **sp; void foo(sp x) { }") 1265 assert 'in argument of foo: unknown type name' in str(e.value) 1266 1267def test_dont_check_unnamable_fields(): 1268 ffi = FFI() 1269 ffi.cdef("struct foo_s { struct { int x; } someone; };") 1270 ffi.verify("struct foo_s { struct { int x; } someone; };") 1271 # assert did not crash 1272 1273def test_nested_anonymous_struct_exact(): 1274 if sys.platform == 'win32': 1275 py.test.skip("nested anonymous struct/union") 1276 ffi = FFI() 1277 ffi.cdef(""" 1278 struct foo_s { struct { int a; char b; }; union { char c, d; }; }; 1279 """) 1280 assert ffi.offsetof("struct foo_s", "c") == 2 * ffi.sizeof("int") 1281 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int") 1282 ffi.verify(""" 1283 struct foo_s { struct { int a; char b; }; union { char c, d; }; }; 1284 """) 1285 p = ffi.new("struct foo_s *") 1286 assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment 1287 p.a = 1234567 1288 p.b = b'X' 1289 p.c = b'Y' 1290 assert p.a == 1234567 1291 assert p.b == b'X' 1292 assert p.c == b'Y' 1293 assert p.d == b'Y' 1294 1295def test_nested_anonymous_struct_exact_error(): 1296 if sys.platform == 'win32': 1297 py.test.skip("nested anonymous struct/union") 1298 ffi = FFI() 1299 ffi.cdef(""" 1300 struct foo_s { struct { int a; char b; }; union { char c, d; }; }; 1301 """) 1302 py.test.raises(VerificationError, ffi.verify, """ 1303 struct foo_s { struct { int a; short b; }; union { char c, d; }; }; 1304 """) 1305 # works fine now 1306 #py.test.raises(VerificationError, ffi.verify, """ 1307 # struct foo_s { struct { int a; char e, b; }; union { char c, d; }; }; 1308 #""") 1309 1310def test_nested_anonymous_struct_inexact_1(): 1311 ffi = FFI() 1312 ffi.cdef(""" 1313 struct foo_s { struct { char b; ...; }; union { char c, d; }; }; 1314 """) 1315 ffi.verify(""" 1316 struct foo_s { int a, padding; char c, d, b; }; 1317 """) 1318 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int") 1319 1320def test_nested_anonymous_struct_inexact_2(): 1321 ffi = FFI() 1322 ffi.cdef(""" 1323 struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; }; 1324 """) 1325 ffi.verify(""" 1326 struct foo_s { int a, padding; char c, d, b; }; 1327 """) 1328 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int") 1329 1330def test_ffi_union(): 1331 ffi = FFI() 1332 ffi.cdef("union foo_u { char x; long *z; };") 1333 ffi.verify("union foo_u { char x; int y; long *z; };") 1334 1335def test_ffi_union_partial(): 1336 ffi = FFI() 1337 ffi.cdef("union foo_u { char x; ...; };") 1338 ffi.verify("union foo_u { char x; int y; };") 1339 assert ffi.sizeof("union foo_u") == 4 1340 1341def test_ffi_union_with_partial_struct(): 1342 ffi = FFI() 1343 ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };") 1344 ffi.verify("struct foo_s { int a; int x; }; " 1345 "union foo_u { char b[32]; struct foo_s s; };") 1346 assert ffi.sizeof("struct foo_s") == 8 1347 assert ffi.sizeof("union foo_u") == 32 1348 1349def test_ffi_union_partial_2(): 1350 ffi = FFI() 1351 ffi.cdef("typedef union { char x; ...; } u1;") 1352 ffi.verify("typedef union { char x; int y; } u1;") 1353 assert ffi.sizeof("u1") == 4 1354 1355def test_ffi_union_with_partial_struct_2(): 1356 ffi = FFI() 1357 ffi.cdef("typedef struct { int x; ...; } s1;" 1358 "typedef union { s1 s; } u1;") 1359 ffi.verify("typedef struct { int a; int x; } s1; " 1360 "typedef union { char b[32]; s1 s; } u1;") 1361 assert ffi.sizeof("s1") == 8 1362 assert ffi.sizeof("u1") == 32 1363 assert ffi.offsetof("u1", "s") == 0 1364 1365def test_ffi_struct_packed(): 1366 if sys.platform == 'win32': 1367 py.test.skip("needs a GCC extension") 1368 ffi = FFI() 1369 ffi.cdef("struct foo_s { int b; ...; };") 1370 ffi.verify(""" 1371 struct foo_s { 1372 char a; 1373 int b; 1374 } __attribute__((packed)); 1375 """) 1376 1377def test_tmpdir(): 1378 import tempfile, os 1379 from testing.udir import udir 1380 tmpdir = tempfile.mkdtemp(dir=str(udir)) 1381 ffi = FFI() 1382 ffi.cdef("int foo(int);") 1383 lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir) 1384 assert os.listdir(tmpdir) 1385 assert lib.foo(100) == 142 1386 1387def test_relative_to(): 1388 py.test.skip("not available") 1389 import tempfile, os 1390 from testing.udir import udir 1391 tmpdir = tempfile.mkdtemp(dir=str(udir)) 1392 ffi = FFI() 1393 ffi.cdef("int foo(int);") 1394 f = open(os.path.join(tmpdir, 'foo.h'), 'w') 1395 f.write("int foo(int a) { return a + 42; }\n") 1396 f.close() 1397 lib = ffi.verify('#include "foo.h"', 1398 include_dirs=['.'], 1399 relative_to=os.path.join(tmpdir, 'x')) 1400 assert lib.foo(100) == 142 1401 1402def test_bug1(): 1403 ffi = FFI() 1404 ffi.cdef(""" 1405 typedef struct tdlhandle_s { ...; } *tdl_handle_t; 1406 typedef struct my_error_code_ { 1407 tdl_handle_t *rh; 1408 } my_error_code_t; 1409 """) 1410 ffi.verify(""" 1411 typedef struct tdlhandle_s { int foo; } *tdl_handle_t; 1412 typedef struct my_error_code_ { 1413 tdl_handle_t *rh; 1414 } my_error_code_t; 1415 """) 1416 1417def test_bool(): 1418 if sys.platform == 'win32': 1419 py.test.skip("_Bool not in MSVC") 1420 ffi = FFI() 1421 ffi.cdef("struct foo_s { _Bool x; };" 1422 "_Bool foo(_Bool); _Bool (*foop)(_Bool);") 1423 lib = ffi.verify(""" 1424 struct foo_s { _Bool x; }; 1425 int foo(int arg) { 1426 return !arg; 1427 } 1428 _Bool _foofunc(_Bool x) { 1429 return !x; 1430 } 1431 _Bool (*foop)(_Bool) = _foofunc; 1432 """) 1433 p = ffi.new("struct foo_s *") 1434 p.x = 1 1435 assert p.x is True 1436 py.test.raises(OverflowError, "p.x = -1") 1437 py.test.raises(TypeError, "p.x = 0.0") 1438 assert lib.foop(1) is False 1439 assert lib.foop(True) is False 1440 assert lib.foop(0) is True 1441 py.test.raises(OverflowError, lib.foop, 42) 1442 py.test.raises(TypeError, lib.foop, 0.0) 1443 assert lib.foo(1) is False 1444 assert lib.foo(True) is False 1445 assert lib.foo(0) is True 1446 py.test.raises(OverflowError, lib.foo, 42) 1447 py.test.raises(TypeError, lib.foo, 0.0) 1448 assert int(ffi.cast("_Bool", long(1))) == 1 1449 assert int(ffi.cast("_Bool", long(0))) == 0 1450 assert int(ffi.cast("_Bool", long(-1))) == 1 1451 assert int(ffi.cast("_Bool", 10**200)) == 1 1452 assert int(ffi.cast("_Bool", 10**40000)) == 1 1453 # 1454 class Foo(object): 1455 def __int__(self): 1456 self.seen = 1 1457 return result 1458 f = Foo() 1459 f.seen = 0 1460 result = 42 1461 assert int(ffi.cast("_Bool", f)) == 1 1462 assert f.seen 1463 f.seen = 0 1464 result = 0 1465 assert int(ffi.cast("_Bool", f)) == 0 1466 assert f.seen 1467 # 1468 py.test.raises(TypeError, ffi.cast, "_Bool", []) 1469 1470def test_bool_on_long_double(): 1471 if sys.platform == 'win32': 1472 py.test.skip("_Bool not in MSVC") 1473 f = 1E-250 1474 if f == 0.0 or f*f != 0.0: 1475 py.test.skip("unexpected precision") 1476 ffi = FFI() 1477 ffi.cdef("long double square(long double f); _Bool opposite(_Bool);") 1478 lib = ffi.verify("long double square(long double f) { return f*f; }\n" 1479 "_Bool opposite(_Bool x) { return !x; }") 1480 f0 = lib.square(0.0) 1481 f2 = lib.square(f) 1482 f3 = lib.square(f * 2.0) 1483 if repr(f2) == repr(f3): 1484 py.test.skip("long double doesn't have enough precision") 1485 assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double' 1486 assert int(ffi.cast("_Bool", f2)) == 1 1487 assert int(ffi.cast("_Bool", f3)) == 1 1488 assert int(ffi.cast("_Bool", f0)) == 0 1489 py.test.raises(TypeError, lib.opposite, f2) 1490 1491def test_cannot_pass_float(): 1492 for basetype in ['char', 'short', 'int', 'long', 'long long']: 1493 for sign in ['signed', 'unsigned']: 1494 type = '%s %s' % (sign, basetype) 1495 ffi = FFI() 1496 ffi.cdef("struct foo_s { %s x; };\n" 1497 "int foo(%s);" % (type, type)) 1498 lib = ffi.verify(""" 1499 struct foo_s { %s x; }; 1500 int foo(%s arg) { 1501 return !arg; 1502 } 1503 """ % (type, type)) 1504 p = ffi.new("struct foo_s *") 1505 py.test.raises(TypeError, "p.x = 0.0") 1506 assert lib.foo(42) == 0 1507 assert lib.foo(0) == 1 1508 py.test.raises(TypeError, lib.foo, 0.0) 1509 1510def test_addressof(): 1511 ffi = FFI() 1512 ffi.cdef(""" 1513 struct point_s { int x, y; }; 1514 struct foo_s { int z; struct point_s point; }; 1515 struct point_s sum_coord(struct point_s *); 1516 """) 1517 lib = ffi.verify(""" 1518 struct point_s { int x, y; }; 1519 struct foo_s { int z; struct point_s point; }; 1520 struct point_s sum_coord(struct point_s *point) { 1521 struct point_s r; 1522 r.x = point->x + point->y; 1523 r.y = point->x - point->y; 1524 return r; 1525 } 1526 """) 1527 p = ffi.new("struct foo_s *") 1528 p.point.x = 16 1529 p.point.y = 9 1530 py.test.raises(TypeError, lib.sum_coord, p.point) 1531 res = lib.sum_coord(ffi.addressof(p.point)) 1532 assert res.x == 25 1533 assert res.y == 7 1534 res2 = lib.sum_coord(ffi.addressof(res)) 1535 assert res2.x == 32 1536 assert res2.y == 18 1537 py.test.raises(TypeError, lib.sum_coord, res2) 1538 1539def test_callback_in_thread(): 1540 py.test.xfail("adapt or remove") 1541 if sys.platform == 'win32': 1542 py.test.skip("pthread only") 1543 import os, subprocess, imp 1544 arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py') 1545 g = subprocess.Popen([sys.executable, arg, 1546 os.path.dirname(imp.find_module('cffi')[1])]) 1547 result = g.wait() 1548 assert result == 0 1549 1550def test_keepalive_lib(): 1551 py.test.xfail("adapt or remove") 1552 ffi = FFI() 1553 ffi.cdef("int foobar(void);") 1554 lib = ffi.verify("int foobar(void) { return 42; }") 1555 func = lib.foobar 1556 ffi_r = weakref.ref(ffi) 1557 lib_r = weakref.ref(lib) 1558 del ffi 1559 import gc; gc.collect() # lib stays alive 1560 assert lib_r() is not None 1561 assert ffi_r() is not None 1562 assert func() == 42 1563 1564def test_keepalive_ffi(): 1565 py.test.xfail("adapt or remove") 1566 ffi = FFI() 1567 ffi.cdef("int foobar(void);") 1568 lib = ffi.verify("int foobar(void) { return 42; }") 1569 func = lib.foobar 1570 ffi_r = weakref.ref(ffi) 1571 lib_r = weakref.ref(lib) 1572 del lib 1573 import gc; gc.collect() # ffi stays alive 1574 assert ffi_r() is not None 1575 assert lib_r() is not None 1576 assert func() == 42 1577 1578def test_FILE_stored_in_stdout(): 1579 if not sys.platform.startswith('linux'): 1580 py.test.skip("likely, we cannot assign to stdout") 1581 ffi = FFI() 1582 ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);") 1583 lib = ffi.verify(""" 1584 #include <stdio.h> 1585 FILE *setstdout(FILE *f) { 1586 FILE *result = stdout; 1587 stdout = f; 1588 return result; 1589 } 1590 """) 1591 import os 1592 fdr, fdw = os.pipe() 1593 fw1 = os.fdopen(fdw, 'wb', 256) 1594 old_stdout = lib.setstdout(fw1) 1595 try: 1596 # 1597 fw1.write(b"X") 1598 r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42)) 1599 fw1.close() 1600 assert r == len("hello, 42!\n") 1601 # 1602 finally: 1603 lib.setstdout(old_stdout) 1604 # 1605 result = os.read(fdr, 256) 1606 os.close(fdr) 1607 # the 'X' might remain in the user-level buffer of 'fw1' and 1608 # end up showing up after the 'hello, 42!\n' 1609 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX" 1610 1611def test_FILE_stored_explicitly(): 1612 ffi = FFI() 1613 ffi.cdef("int myprintf11(const char *, int); FILE *myfile;") 1614 lib = ffi.verify(""" 1615 #include <stdio.h> 1616 FILE *myfile; 1617 int myprintf11(const char *out, int value) { 1618 return fprintf(myfile, out, value); 1619 } 1620 """) 1621 import os 1622 fdr, fdw = os.pipe() 1623 fw1 = os.fdopen(fdw, 'wb', 256) 1624 lib.myfile = ffi.cast("FILE *", fw1) 1625 # 1626 fw1.write(b"X") 1627 r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42)) 1628 fw1.close() 1629 assert r == len("hello, 42!\n") 1630 # 1631 result = os.read(fdr, 256) 1632 os.close(fdr) 1633 # the 'X' might remain in the user-level buffer of 'fw1' and 1634 # end up showing up after the 'hello, 42!\n' 1635 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX" 1636 1637def test_global_array_with_missing_length(): 1638 ffi = FFI() 1639 ffi.cdef("int fooarray[];") 1640 lib = ffi.verify("int fooarray[50];") 1641 assert repr(lib.fooarray).startswith("<cdata 'int *'") 1642 1643def test_global_array_with_dotdotdot_length(): 1644 ffi = FFI() 1645 ffi.cdef("int fooarray[...];") 1646 lib = ffi.verify("int fooarray[50];") 1647 assert repr(lib.fooarray).startswith("<cdata 'int[50]'") 1648 1649def test_bad_global_array_with_dotdotdot_length(): 1650 py.test.xfail("was detected only because 23 bytes cannot be divided by 4; " 1651 "redo more generally") 1652 ffi = FFI() 1653 ffi.cdef("int fooarray[...];") 1654 py.test.raises(VerificationError, ffi.verify, "char fooarray[23];") 1655 1656def test_struct_containing_struct(): 1657 ffi = FFI() 1658 ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };") 1659 ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };") 1660 # 1661 ffi = FFI() 1662 ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };") 1663 ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };") 1664 1665def test_struct_returned_by_func(): 1666 ffi = FFI() 1667 ffi.cdef("typedef ... foo_t; foo_t myfunc(void);") 1668 e = py.test.raises(TypeError, ffi.verify, 1669 "typedef struct { int x; } foo_t; " 1670 "foo_t myfunc(void) { foo_t x = { 42 }; return x; }") 1671 assert str(e.value) == ( 1672 "function myfunc: 'foo_t' is used as result type, but is opaque") 1673 1674def test_include(): 1675 ffi1 = FFI() 1676 ffi1.cdef("typedef struct { int x; ...; } foo_t;") 1677 ffi1.verify("typedef struct { int y, x; } foo_t;") 1678 ffi2 = FFI() 1679 ffi2.include(ffi1) 1680 ffi2.cdef("int myfunc(foo_t *);") 1681 lib = ffi2.verify("typedef struct { int y, x; } foo_t;" 1682 "int myfunc(foo_t *p) { return 42 * p->x; }") 1683 res = lib.myfunc(ffi2.new("foo_t *", {'x': 10})) 1684 assert res == 420 1685 res = lib.myfunc(ffi1.new("foo_t *", {'x': -10})) 1686 assert res == -420 1687 1688def test_include_enum(): 1689 ffi1 = FFI() 1690 ffi1.cdef("enum foo_e { AA, ... };") 1691 lib1 = ffi1.verify("enum foo_e { CC, BB, AA };") 1692 ffi2 = FFI() 1693 ffi2.include(ffi1) 1694 ffi2.cdef("int myfunc(enum foo_e);") 1695 lib2 = ffi2.verify("enum foo_e { CC, BB, AA };" 1696 "int myfunc(enum foo_e x) { return (int)x; }") 1697 res = lib2.myfunc(lib2.AA) 1698 assert res == 2 1699 1700def test_named_pointer_as_argument(): 1701 ffi = FFI() 1702 ffi.cdef("typedef struct { int x; } *mystruct_p;\n" 1703 "mystruct_p ff5a(mystruct_p);") 1704 lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n" 1705 "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }") 1706 p = ffi.new("mystruct_p", [-2]) 1707 q = lib.ff5a(p) 1708 assert q == p 1709 assert p.x == 38 1710 1711def test_enum_size(): 1712 cases = [('123', 4, 4294967295), 1713 ('4294967295U', 4, 4294967295), 1714 ('-123', 4, -1), 1715 ('-2147483647-1', 4, -1), 1716 ] 1717 if FFI().sizeof("long") == 8: 1718 cases += [('4294967296L', 8, 2**64-1), 1719 ('%dUL' % (2**64-1), 8, 2**64-1), 1720 ('-2147483649L', 8, -1), 1721 ('%dL-1L' % (1-2**63), 8, -1)] 1722 for hidden_value, expected_size, expected_minus1 in cases: 1723 if sys.platform == 'win32' and 'U' in hidden_value: 1724 continue # skipped on Windows 1725 ffi = FFI() 1726 ffi.cdef("enum foo_e { AA, BB, ... };") 1727 lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value) 1728 assert lib.AA == 0 1729 assert lib.BB == eval(hidden_value.replace('U', '').replace('L', '')) 1730 assert ffi.sizeof("enum foo_e") == expected_size 1731 if sys.platform != 'win32': 1732 assert int(ffi.cast("enum foo_e", -1)) == expected_minus1 1733 # test with the large value hidden: 1734 # disabled so far, doesn't work 1735## for hidden_value, expected_size, expected_minus1 in cases: 1736## ffi = FFI() 1737## ffi.cdef("enum foo_e { AA, BB, ... };") 1738## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value) 1739## assert lib.AA == 0 1740## assert ffi.sizeof("enum foo_e") == expected_size 1741## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1 1742 1743def test_enum_bug118(): 1744 maxulong = 256 ** FFI().sizeof("unsigned long") - 1 1745 for c2, c2c in [(-1, ''), 1746 (-1, ''), 1747 (0xffffffff, 'U'), 1748 (maxulong, 'UL'), 1749 (-int(maxulong / 3), 'L')]: 1750 if c2c and sys.platform == 'win32': 1751 continue # enums may always be signed with MSVC 1752 ffi = FFI() 1753 ffi.cdef("enum foo_e { AA };") 1754 lib = ffi.verify("enum foo_e { AA=%s%s };" % (c2, c2c)) 1755 assert lib.AA == c2 1756 1757def test_string_to_voidp_arg(): 1758 ffi = FFI() 1759 ffi.cdef("int myfunc(void *);") 1760 lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }") 1761 res = lib.myfunc(b"hi!") 1762 assert res == ord(b"h") 1763 p = ffi.new("char[]", b"gah") 1764 res = lib.myfunc(p) 1765 assert res == ord(b"g") 1766 res = lib.myfunc(ffi.cast("void *", p)) 1767 assert res == ord(b"g") 1768 res = lib.myfunc(ffi.cast("int *", p)) 1769 assert res == ord(b"g") 1770 1771def test_callback_indirection(): 1772 ffi = FFI() 1773 ffi.cdef(""" 1774 int (*python_callback)(int how_many, int *values); 1775 int (*const c_callback)(int,...); /* pass this ptr to C routines */ 1776 int some_c_function(int(*cb)(int,...)); 1777 """) 1778 lib = ffi.verify(""" 1779 #include <stdarg.h> 1780 #ifdef _WIN32 1781 #include <malloc.h> 1782 #define alloca _alloca 1783 #else 1784 # ifdef __FreeBSD__ 1785 # include <stdlib.h> 1786 # else 1787 # include <alloca.h> 1788 # endif 1789 #endif 1790 static int (*python_callback)(int how_many, int *values); 1791 static int c_callback(int how_many, ...) { 1792 va_list ap; 1793 /* collect the "..." arguments into the values[] array */ 1794 int i, *values = alloca((size_t)how_many * sizeof(int)); 1795 va_start(ap, how_many); 1796 for (i=0; i<how_many; i++) 1797 values[i] = va_arg(ap, int); 1798 va_end(ap); 1799 return python_callback(how_many, values); 1800 } 1801 int some_c_function(int(*cb)(int,...)) { 1802 int result = cb(2, 10, 20); 1803 result += cb(3, 30, 40, 50); 1804 return result; 1805 } 1806 """) 1807 seen = [] 1808 @ffi.callback("int(int, int*)") 1809 def python_callback(how_many, values): 1810 seen.append([values[i] for i in range(how_many)]) 1811 return 42 1812 lib.python_callback = python_callback 1813 1814 res = lib.some_c_function(lib.c_callback) 1815 assert res == 84 1816 assert seen == [[10, 20], [30, 40, 50]] 1817 1818def test_floatstar_argument(): 1819 ffi = FFI() 1820 ffi.cdef("float sum3floats(float *);") 1821 lib = ffi.verify(""" 1822 float sum3floats(float *f) { 1823 return f[0] + f[1] + f[2]; 1824 } 1825 """) 1826 assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5 1827 p = ffi.new("float[]", (1.5, 2.5, 3.5)) 1828 assert lib.sum3floats(p) == 7.5 1829 1830def test_charstar_argument(): 1831 ffi = FFI() 1832 ffi.cdef("char sum3chars(char *);") 1833 lib = ffi.verify(""" 1834 char sum3chars(char *f) { 1835 return (char)(f[0] + f[1] + f[2]); 1836 } 1837 """) 1838 assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60' 1839 p = ffi.new("char[]", b'\x10\x20\x30') 1840 assert lib.sum3chars(p) == b'\x60' 1841 1842def test_passing_string_or_NULL(): 1843 ffi = FFI() 1844 ffi.cdef("int seeme1(char *); int seeme2(int *);") 1845 lib = ffi.verify(""" 1846 int seeme1(char *x) { 1847 return (x == NULL); 1848 } 1849 int seeme2(int *x) { 1850 return (x == NULL); 1851 } 1852 """) 1853 assert lib.seeme1(b"foo") == 0 1854 assert lib.seeme1(ffi.NULL) == 1 1855 assert lib.seeme2([42, 43]) == 0 1856 assert lib.seeme2(ffi.NULL) == 1 1857 py.test.raises(TypeError, lib.seeme1, None) 1858 py.test.raises(TypeError, lib.seeme2, None) 1859 py.test.raises(TypeError, lib.seeme1, 0.0) 1860 py.test.raises(TypeError, lib.seeme2, 0.0) 1861 py.test.raises(TypeError, lib.seeme1, 0) 1862 py.test.raises(TypeError, lib.seeme2, 0) 1863 zeroL = 99999999999999999999 1864 zeroL -= 99999999999999999999 1865 py.test.raises(TypeError, lib.seeme2, zeroL) 1866 1867def test_typeof_function(): 1868 ffi = FFI() 1869 ffi.cdef("int foo(int, char);") 1870 lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }") 1871 ctype = ffi.typeof(lib.foo) 1872 assert len(ctype.args) == 2 1873 assert ctype.result == ffi.typeof("int") 1874 1875def test_call_with_voidstar_arg(): 1876 ffi = FFI() 1877 ffi.cdef("int f(void *);") 1878 lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }") 1879 assert lib.f(b"foobar") == ord(b"f") 1880 1881def test_dir(): 1882 ffi = FFI() 1883 ffi.cdef("""void somefunc(void); 1884 extern int somevar, somearray[2]; 1885 static char *const sv2; 1886 enum my_e { AA, BB, ... }; 1887 #define FOO ...""") 1888 lib = ffi.verify("""void somefunc(void) { } 1889 int somevar, somearray[2]; 1890 #define sv2 "text" 1891 enum my_e { AA, BB }; 1892 #define FOO 42""") 1893 assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray', 1894 'somefunc', 'somevar', 'sv2'] 1895 1896def test_typeof_func_with_struct_argument(): 1897 ffi = FFI() 1898 ffi.cdef("""struct s { int a; }; int foo(struct s);""") 1899 lib = ffi.verify("""struct s { int a; }; 1900 int foo(struct s x) { return x.a; }""") 1901 s = ffi.new("struct s *", [-1234]) 1902 m = lib.foo(s[0]) 1903 assert m == -1234 1904 assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>" 1905 1906def test_bug_const_char_ptr_array_1(): 1907 ffi = FFI() 1908 ffi.cdef("""const char *a[...];""") 1909 lib = ffi.verify("""const char *a[5];""") 1910 assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>" 1911 1912def test_bug_const_char_ptr_array_2(): 1913 ffi = FFI() 1914 ffi.cdef("""const int a[];""") 1915 lib = ffi.verify("""const int a[5];""") 1916 assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>" 1917 1918def _test_various_calls(force_libffi): 1919 cdef_source = """ 1920 int xvalue; 1921 long long ivalue, rvalue; 1922 float fvalue; 1923 double dvalue; 1924 long double Dvalue; 1925 signed char tf_bb(signed char x, signed char c); 1926 unsigned char tf_bB(signed char x, unsigned char c); 1927 short tf_bh(signed char x, short c); 1928 unsigned short tf_bH(signed char x, unsigned short c); 1929 int tf_bi(signed char x, int c); 1930 unsigned int tf_bI(signed char x, unsigned int c); 1931 long tf_bl(signed char x, long c); 1932 unsigned long tf_bL(signed char x, unsigned long c); 1933 long long tf_bq(signed char x, long long c); 1934 unsigned long long tf_bQ(signed char x, unsigned long long c); 1935 float tf_bf(signed char x, float c); 1936 double tf_bd(signed char x, double c); 1937 long double tf_bD(signed char x, long double c); 1938 """ 1939 if force_libffi: 1940 cdef_source = (cdef_source 1941 .replace('tf_', '(*const tf_') 1942 .replace('(signed char x', ')(signed char x')) 1943 ffi = FFI() 1944 ffi.cdef(cdef_source) 1945 lib = ffi.verify(""" 1946 int xvalue; 1947 long long ivalue, rvalue; 1948 float fvalue; 1949 double dvalue; 1950 long double Dvalue; 1951 1952 typedef signed char b_t; 1953 typedef unsigned char B_t; 1954 typedef short h_t; 1955 typedef unsigned short H_t; 1956 typedef int i_t; 1957 typedef unsigned int I_t; 1958 typedef long l_t; 1959 typedef unsigned long L_t; 1960 typedef long long q_t; 1961 typedef unsigned long long Q_t; 1962 typedef float f_t; 1963 typedef double d_t; 1964 typedef long double D_t; 1965 #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c; 1966 #define R(letter) return (letter##_t)rvalue; 1967 1968 signed char tf_bb(signed char x, signed char c) { S(i) R(b) } 1969 unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) } 1970 short tf_bh(signed char x, short c) { S(i) R(h) } 1971 unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) } 1972 int tf_bi(signed char x, int c) { S(i) R(i) } 1973 unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) } 1974 long tf_bl(signed char x, long c) { S(i) R(l) } 1975 unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) } 1976 long long tf_bq(signed char x, long long c) { S(i) R(q) } 1977 unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) } 1978 float tf_bf(signed char x, float c) { S(f) R(f) } 1979 double tf_bd(signed char x, double c) { S(d) R(d) } 1980 long double tf_bD(signed char x, long double c) { S(D) R(D) } 1981 """) 1982 lib.rvalue = 0x7182838485868788 1983 for kind, cname in [('b', 'signed char'), 1984 ('B', 'unsigned char'), 1985 ('h', 'short'), 1986 ('H', 'unsigned short'), 1987 ('i', 'int'), 1988 ('I', 'unsigned int'), 1989 ('l', 'long'), 1990 ('L', 'unsigned long'), 1991 ('q', 'long long'), 1992 ('Q', 'unsigned long long'), 1993 ('f', 'float'), 1994 ('d', 'double'), 1995 ('D', 'long double')]: 1996 sign = +1 if 'unsigned' in cname else -1 1997 lib.xvalue = 0 1998 lib.ivalue = 0 1999 lib.fvalue = 0 2000 lib.dvalue = 0 2001 lib.Dvalue = 0 2002 fun = getattr(lib, 'tf_b' + kind) 2003 res = fun(-42, sign * 99) 2004 if kind == 'D': 2005 res = float(res) 2006 assert res == int(ffi.cast(cname, 0x7182838485868788)) 2007 assert lib.xvalue == -42 2008 if kind in 'fdD': 2009 assert float(getattr(lib, kind + 'value')) == -99.0 2010 else: 2011 assert lib.ivalue == sign * 99 2012 2013def test_various_calls_direct(): 2014 _test_various_calls(force_libffi=False) 2015 2016def test_various_calls_libffi(): 2017 _test_various_calls(force_libffi=True) 2018 2019def test_ptr_to_opaque(): 2020 ffi = FFI() 2021 ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);") 2022 lib = ffi.verify(""" 2023 #include <stdlib.h> 2024 typedef struct { int x; } foo_t; 2025 int f1(foo_t* p) { 2026 int x = p->x; 2027 free(p); 2028 return x; 2029 } 2030 foo_t *f2(int x) { 2031 foo_t *p = malloc(sizeof(foo_t)); 2032 p->x = x; 2033 return p; 2034 } 2035 """) 2036 p = lib.f2(42) 2037 x = lib.f1(p) 2038 assert x == 42 2039 2040def _run_in_multiple_threads(test1): 2041 test1() 2042 import sys 2043 try: 2044 import thread 2045 except ImportError: 2046 import _thread as thread 2047 errors = [] 2048 def wrapper(lock): 2049 try: 2050 test1() 2051 except: 2052 errors.append(sys.exc_info()) 2053 lock.release() 2054 locks = [] 2055 for i in range(10): 2056 _lock = thread.allocate_lock() 2057 _lock.acquire() 2058 thread.start_new_thread(wrapper, (_lock,)) 2059 locks.append(_lock) 2060 for _lock in locks: 2061 _lock.acquire() 2062 if errors: 2063 raise errors[0][1] 2064 2065def test_errno_working_even_with_pypys_jit(): 2066 ffi = FFI() 2067 ffi.cdef("int f(int);") 2068 lib = ffi.verify(""" 2069 #include <errno.h> 2070 int f(int x) { return (errno = errno + x); } 2071 """) 2072 @_run_in_multiple_threads 2073 def test1(): 2074 ffi.errno = 0 2075 for i in range(10000): 2076 e = lib.f(1) 2077 assert e == i + 1 2078 assert ffi.errno == e 2079 for i in range(10000): 2080 ffi.errno = i 2081 e = lib.f(42) 2082 assert e == i + 42 2083 2084def test_getlasterror_working_even_with_pypys_jit(): 2085 if sys.platform != 'win32': 2086 py.test.skip("win32-only test") 2087 ffi = FFI() 2088 ffi.cdef("void SetLastError(DWORD);") 2089 lib = ffi.dlopen("Kernel32.dll") 2090 @_run_in_multiple_threads 2091 def test1(): 2092 for i in range(10000): 2093 n = (1 << 29) + i 2094 lib.SetLastError(n) 2095 assert ffi.getwinerror()[0] == n 2096 2097def test_verify_dlopen_flags(): 2098 if not hasattr(sys, 'setdlopenflags'): 2099 py.test.skip("requires sys.setdlopenflags()") 2100 # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted 2101 # promptly, like on PyPy, then other tests may see the same 2102 # exported symbols as well. So we must not export a simple name 2103 # like 'foo'! 2104 old = sys.getdlopenflags() 2105 try: 2106 ffi1 = FFI() 2107 ffi1.cdef("int foo_verify_dlopen_flags_1;") 2108 sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW) 2109 lib1 = ffi1.verify("int foo_verify_dlopen_flags_1;") 2110 finally: 2111 sys.setdlopenflags(old) 2112 2113 ffi2 = FFI() 2114 ffi2.cdef("int *getptr(void);") 2115 lib2 = ffi2.verify(""" 2116 extern int foo_verify_dlopen_flags_1; 2117 static int *getptr(void) { return &foo_verify_dlopen_flags_1; } 2118 """) 2119 p = lib2.getptr() 2120 assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags_1') == p 2121 2122def test_consider_not_implemented_function_type(): 2123 ffi = FFI() 2124 ffi.cdef("typedef union { int a; float b; } Data;" 2125 "typedef struct { int a:2; } MyStr;" 2126 "typedef void (*foofunc_t)(Data);" 2127 "typedef Data (*bazfunc_t)(void);" 2128 "typedef MyStr (*barfunc_t)(void);") 2129 fooptr = ffi.cast("foofunc_t", 123) 2130 bazptr = ffi.cast("bazfunc_t", 123) 2131 barptr = ffi.cast("barfunc_t", 123) 2132 # assert did not crash so far 2133 e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *")) 2134 assert str(e.value) == ( 2135 "ctype 'Data' not supported as argument by libffi. Unions are only " 2136 "supported as argument if the function is 'API mode' and " 2137 "non-variadic (i.e. declared inside ffibuilder.cdef()+" 2138 "ffibuilder.set_source() and not taking a final '...' argument)") 2139 e = py.test.raises(NotImplementedError, bazptr) 2140 assert str(e.value) == ( 2141 "ctype 'Data' not supported as return value by libffi. Unions are " 2142 "only supported as return value if the function is 'API mode' and " 2143 "non-variadic (i.e. declared inside ffibuilder.cdef()+" 2144 "ffibuilder.set_source() and not taking a final '...' argument)") 2145 e = py.test.raises(NotImplementedError, barptr) 2146 assert str(e.value) == ( 2147 "ctype 'MyStr' not supported as return value. It is a struct with " 2148 "bit fields, which libffi does not support. Such structs are only " 2149 "supported as return value if the function is 'API mode' and non-" 2150 "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder." 2151 "set_source() and not taking a final '...' argument)") 2152 2153def test_verify_extra_arguments(): 2154 ffi = FFI() 2155 ffi.cdef("#define ABA ...") 2156 lib = ffi.verify("", define_macros=[('ABA', '42')]) 2157 assert lib.ABA == 42 2158 2159def test_implicit_unicode_on_windows(): 2160 from cffi import FFIError 2161 if sys.platform != 'win32': 2162 py.test.skip("win32-only test") 2163 ffi = FFI() 2164 e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);") 2165 assert str(e.value) == ("The Windows type 'LPTSTR' is only available after" 2166 " you call ffi.set_unicode()") 2167 for with_unicode in [True, False]: 2168 ffi = FFI() 2169 ffi.set_unicode(with_unicode) 2170 ffi.cdef(""" 2171 DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, 2172 DWORD nSize); 2173 """) 2174 lib = ffi.verify(""" 2175 #include <windows.h> 2176 """, libraries=['Kernel32']) 2177 outbuf = ffi.new("TCHAR[]", 200) 2178 n = lib.GetModuleFileName(ffi.NULL, outbuf, 500) 2179 assert 0 < n < 500 2180 for i in range(n): 2181 #print repr(outbuf[i]) 2182 assert ord(outbuf[i]) != 0 2183 assert ord(outbuf[n]) == 0 2184 assert ord(outbuf[0]) < 128 # should be a letter, or '\' 2185 2186def test_define_known_value(): 2187 ffi = FFI() 2188 ffi.cdef("#define FOO 0x123") 2189 lib = ffi.verify("#define FOO 0x123") 2190 assert lib.FOO == 0x123 2191 2192def test_define_wrong_value(): 2193 ffi = FFI() 2194 ffi.cdef("#define FOO 123") 2195 lib = ffi.verify("#define FOO 124") # used to complain 2196 e = py.test.raises(ffi.error, "lib.FOO") 2197 assert str(e.value) == ("the C compiler says 'FOO' is equal to 124 (0x7c)," 2198 " but the cdef disagrees") 2199 2200def test_some_integer_type_for_issue73(): 2201 ffi = FFI() 2202 ffi.cdef(""" 2203 typedef int... AnIntegerWith32Bits; 2204 typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void); 2205 AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger); 2206 """) 2207 lib = ffi.verify(""" 2208 #ifdef __LP64__ 2209 typedef int AnIntegerWith32Bits; 2210 #else 2211 typedef long AnIntegerWith32Bits; 2212 #endif 2213 typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void); 2214 AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger f) { 2215 return f(); 2216 } 2217 """) 2218 @ffi.callback("AFunctionReturningInteger") 2219 def add(): 2220 return 3 + 4 2221 x = lib.InvokeFunction(add) 2222 assert x == 7 2223 2224def test_unsupported_some_primitive_types(): 2225 ffi = FFI() 2226 py.test.raises((FFIError, # with pycparser <= 2.17 2227 CDefError), # with pycparser >= 2.18 2228 ffi.cdef, """typedef void... foo_t;""") 2229 # 2230 ffi.cdef("typedef int... foo_t;") 2231 py.test.raises(VerificationError, ffi.verify, "typedef float foo_t;") 2232 2233def test_windows_dllimport_data(): 2234 if sys.platform != 'win32': 2235 py.test.skip("Windows only") 2236 from testing.udir import udir 2237 tmpfile = udir.join('dllimport_data.c') 2238 tmpfile.write('int my_value = 42;\n') 2239 ffi = FFI() 2240 ffi.cdef("int my_value;") 2241 lib = ffi.verify("extern __declspec(dllimport) int my_value;", 2242 sources = [str(tmpfile)]) 2243 assert lib.my_value == 42 2244 2245def test_macro_var(): 2246 ffi = FFI() 2247 ffi.cdef("int myarray[50], my_value;") 2248 lib = ffi.verify(""" 2249 int myarray[50]; 2250 int *get_my_value(void) { 2251 static int index = 0; 2252 return &myarray[index++]; 2253 } 2254 #define my_value (*get_my_value()) 2255 """) 2256 assert lib.my_value == 0 # [0] 2257 lib.my_value = 42 # [1] 2258 assert lib.myarray[1] == 42 2259 assert lib.my_value == 0 # [2] 2260 lib.myarray[3] = 63 2261 assert lib.my_value == 63 # [3] 2262 p = ffi.addressof(lib, 'my_value') # [4] 2263 assert p[-1] == 63 2264 assert p[0] == 0 2265 assert p == lib.myarray + 4 2266 p[1] = 82 2267 assert lib.my_value == 82 # [5] 2268 2269def test_const_pointer_to_pointer(): 2270 ffi = FFI() 2271 ffi.cdef("struct s { char *const *a; };") 2272 ffi.verify("struct s { char *const *a; };") 2273 2274def test_share_FILE(): 2275 ffi1 = FFI() 2276 ffi1.cdef("void do_stuff(FILE *);") 2277 lib1 = ffi1.verify("void do_stuff(FILE *f) { (void)f; }") 2278 ffi2 = FFI() 2279 ffi2.cdef("FILE *barize(void);") 2280 lib2 = ffi2.verify("FILE *barize(void) { return NULL; }") 2281 lib1.do_stuff(lib2.barize()) 2282 2283def test_win_common_types(): 2284 if sys.platform != 'win32': 2285 py.test.skip("Windows only") 2286 ffi = FFI() 2287 ffi.set_unicode(True) 2288 ffi.verify("") 2289 assert ffi.typeof("PBYTE") is ffi.typeof("unsigned char *") 2290 if sys.maxsize > 2**32: 2291 expected = "unsigned long long" 2292 else: 2293 expected = "unsigned int" 2294 assert ffi.typeof("UINT_PTR") is ffi.typeof(expected) 2295 assert ffi.typeof("PTSTR") is ffi.typeof("wchar_t *") 2296 2297def _only_test_on_linux_intel(): 2298 if not sys.platform.startswith('linux'): 2299 py.test.skip('only running the memory-intensive test on Linux') 2300 import platform 2301 machine = platform.machine() 2302 if 'x86' not in machine and 'x64' not in machine: 2303 py.test.skip('only running the memory-intensive test on x86/x64') 2304 2305def test_ffi_gc_size_arg(): 2306 _only_test_on_linux_intel() 2307 ffi = FFI() 2308 ffi.cdef("void *malloc(size_t); void free(void *);") 2309 lib = ffi.verify(r""" 2310 #include <stdlib.h> 2311 """) 2312 for i in range(2000): 2313 p = lib.malloc(20*1024*1024) # 20 MB 2314 p1 = ffi.cast("char *", p) 2315 for j in range(0, 20*1024*1024, 4096): 2316 p1[j] = b'!' 2317 p = ffi.gc(p, lib.free, 20*1024*1024) 2318 del p 2319 # with PyPy's GC, the above would rapidly consume 40 GB of RAM 2320 # without the third argument to ffi.gc() 2321 2322def test_ffi_gc_size_arg_2(): 2323 # a variant of the above: this "attack" works on cpython's cyclic gc too 2324 # and I found no obvious way to prevent that. So for now, this test 2325 # is skipped on CPython, where it eats all the memory. 2326 if '__pypy__' not in sys.builtin_module_names: 2327 py.test.skip("find a way to tweak the cyclic GC of CPython") 2328 _only_test_on_linux_intel() 2329 ffi = FFI() 2330 ffi.cdef("void *malloc(size_t); void free(void *);") 2331 lib = ffi.verify(r""" 2332 #include <stdlib.h> 2333 """) 2334 class X(object): 2335 pass 2336 for i in range(2000): 2337 p = lib.malloc(50*1024*1024) # 50 MB 2338 p1 = ffi.cast("char *", p) 2339 for j in range(0, 50*1024*1024, 4096): 2340 p1[j] = b'!' 2341 p = ffi.gc(p, lib.free, 50*1024*1024) 2342 x = X() 2343 x.p = p 2344 x.cyclic = x 2345 del p, x 2346 2347def test_ffi_new_with_cycles(): 2348 # still another variant, with ffi.new() 2349 if '__pypy__' not in sys.builtin_module_names: 2350 py.test.skip("find a way to tweak the cyclic GC of CPython") 2351 ffi = FFI() 2352 ffi.cdef("") 2353 lib = ffi.verify("") 2354 class X(object): 2355 pass 2356 for i in range(2000): 2357 p = ffi.new("char[]", 50*1024*1024) # 50 MB 2358 for j in range(0, 50*1024*1024, 4096): 2359 p[j] = b'!' 2360 x = X() 2361 x.p = p 2362 x.cyclic = x 2363 del p, x 2364