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