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