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