PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/_rawffi/test/test__rawffi.py

https://bitbucket.org/pypy/pypy/
Python | 1273 lines | 1270 code | 3 blank | 0 comment | 0 complexity | 71f1c6bfa33b769cf0679ecaf86de878 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.translator.platform import platform
  2. from rpython.translator.tool.cbuild import ExternalCompilationInfo
  3. from rpython.translator import cdir
  4. from pypy.module._rawffi.interp_rawffi import TYPEMAP, TYPEMAP_FLOAT_LETTERS
  5. from pypy.module._rawffi.tracker import Tracker
  6. import os, sys, py
  7. class AppTestFfi:
  8. spaceconfig = dict(usemodules=['_rawffi', 'struct'])
  9. def prepare_c_example():
  10. from rpython.tool.udir import udir
  11. c_file = udir.ensure("test__rawffi", dir=1).join("xlib.c")
  12. c_file.write(py.code.Source('''
  13. #include "src/precommondefs.h"
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <errno.h>
  17. struct x
  18. {
  19. int x1;
  20. short x2;
  21. char x3;
  22. struct x* next;
  23. };
  24. RPY_EXPORTED
  25. void nothing()
  26. {
  27. }
  28. RPY_EXPORTED
  29. char inner_struct_elem(struct x *x1)
  30. {
  31. return x1->next->x3;
  32. }
  33. RPY_EXPORTED
  34. struct x* create_double_struct()
  35. {
  36. struct x* x1, *x2;
  37. x1 = (struct x*)malloc(sizeof(struct x));
  38. x2 = (struct x*)malloc(sizeof(struct x));
  39. x1->next = x2;
  40. x2->x2 = 3;
  41. return x1;
  42. }
  43. RPY_EXPORTED
  44. void free_double_struct(struct x* x1)
  45. {
  46. free(x1->next);
  47. free(x1);
  48. }
  49. const char *static_str = "xxxxxx";
  50. RPY_EXPORTED
  51. long static_int = 42;
  52. RPY_EXPORTED
  53. double static_double = 42.42;
  54. RPY_EXPORTED
  55. long double static_longdouble = 42.42;
  56. RPY_EXPORTED
  57. unsigned short add_shorts(short one, short two)
  58. {
  59. return one + two;
  60. }
  61. RPY_EXPORTED
  62. void* get_raw_pointer()
  63. {
  64. return (void*)add_shorts;
  65. }
  66. RPY_EXPORTED
  67. char get_char(char* s, unsigned short num)
  68. {
  69. return s[num];
  70. }
  71. RPY_EXPORTED
  72. const char *char_check(char x, char y)
  73. {
  74. if (y == static_str[0])
  75. return static_str;
  76. return NULL;
  77. }
  78. RPY_EXPORTED
  79. int get_array_elem(int* stuff, int num)
  80. {
  81. return stuff[num];
  82. }
  83. RPY_EXPORTED
  84. struct x* get_array_elem_s(struct x** array, int num)
  85. {
  86. return array[num];
  87. }
  88. RPY_EXPORTED
  89. long long some_huge_value()
  90. {
  91. return 1LL<<42;
  92. }
  93. RPY_EXPORTED
  94. unsigned long long some_huge_uvalue()
  95. {
  96. return 1LL<<42;
  97. }
  98. RPY_EXPORTED
  99. long long pass_ll(long long x)
  100. {
  101. return x;
  102. }
  103. static int prebuilt_array1[] = {3};
  104. RPY_EXPORTED
  105. int* allocate_array()
  106. {
  107. return prebuilt_array1;
  108. }
  109. RPY_EXPORTED
  110. long long runcallback(long long(*callback)())
  111. {
  112. return callback();
  113. }
  114. struct x_y {
  115. long x;
  116. long y;
  117. };
  118. RPY_EXPORTED
  119. long sum_x_y(struct x_y s) {
  120. return s.x + s.y;
  121. }
  122. RPY_EXPORTED
  123. long op_x_y(struct x_y s, long(*callback)(struct x_y))
  124. {
  125. return callback(s);
  126. }
  127. struct s2h {
  128. short x;
  129. short y;
  130. };
  131. RPY_EXPORTED
  132. struct s2h give(short x, short y) {
  133. struct s2h out;
  134. out.x = x;
  135. out.y = y;
  136. return out;
  137. }
  138. RPY_EXPORTED
  139. struct s2h perturb(struct s2h inp) {
  140. inp.x *= 2;
  141. inp.y *= 3;
  142. return inp;
  143. }
  144. struct s2a {
  145. int bah[2];
  146. };
  147. RPY_EXPORTED
  148. struct s2a get_s2a(void) {
  149. struct s2a outp;
  150. outp.bah[0] = 4;
  151. outp.bah[1] = 5;
  152. return outp;
  153. }
  154. RPY_EXPORTED
  155. int check_s2a(struct s2a inp) {
  156. return (inp.bah[0] == 4 && inp.bah[1] == 5);
  157. }
  158. RPY_EXPORTED
  159. int AAA_first_ordinal_function()
  160. {
  161. return 42;
  162. }
  163. typedef union {
  164. short x;
  165. long y;
  166. } UN;
  167. RPY_EXPORTED
  168. UN ret_un_func(UN inp)
  169. {
  170. inp.y = inp.x * 100;
  171. return inp;
  172. }
  173. RPY_EXPORTED
  174. int check_errno(int incoming)
  175. {
  176. int old_errno = errno;
  177. errno = incoming;
  178. return old_errno;
  179. }
  180. #ifdef _WIN32
  181. #include <Windows.h>
  182. RPY_EXPORTED
  183. int check_last_error(int incoming)
  184. {
  185. int old_errno = GetLastError();
  186. SetLastError(incoming);
  187. return old_errno;
  188. }
  189. #endif
  190. '''))
  191. eci = ExternalCompilationInfo(include_dirs=[cdir])
  192. return str(platform.compile([c_file], eci, 'x', standalone=False))
  193. prepare_c_example = staticmethod(prepare_c_example)
  194. def setup_class(cls):
  195. space = cls.space
  196. from rpython.rlib.clibffi import get_libc_name
  197. cls.w_lib_name = space.wrap(cls.prepare_c_example())
  198. cls.w_libc_name = space.wrap(get_libc_name())
  199. if sys.platform == 'win32':
  200. cls.w_iswin32 = space.wrap(True)
  201. cls.w_libm_name = space.wrap('msvcrt')
  202. else:
  203. cls.w_iswin32 = space.wrap(False)
  204. cls.w_libm_name = space.wrap('libm.so')
  205. if sys.platform == "darwin":
  206. cls.w_libm_name = space.wrap('libm.dylib')
  207. cls.w_platform = space.wrap(platform.name)
  208. cls.w_sizes_and_alignments = space.wrap(dict(
  209. [(k, (v.c_size, v.c_alignment)) for k,v in TYPEMAP.iteritems()]))
  210. cls.w_float_typemap = space.wrap(TYPEMAP_FLOAT_LETTERS)
  211. def test_libload(self):
  212. import _rawffi
  213. _rawffi.CDLL(self.libc_name)
  214. def test_libload_fail(self):
  215. import _rawffi
  216. try:
  217. _rawffi.CDLL("xxxxx_this_name_does_not_exist_xxxxx")
  218. except OSError as e:
  219. print e
  220. assert str(e).startswith(
  221. "Cannot load library xxxxx_this_name_does_not_exist_xxxxx: ")
  222. else:
  223. raise AssertionError("did not fail??")
  224. def test_libload_None(self):
  225. if self.iswin32:
  226. skip("unix specific")
  227. import _rawffi
  228. # this should return *all* loaded libs, dlopen(NULL)
  229. dll = _rawffi.CDLL(None)
  230. func = dll.ptr('rand', [], 'i')
  231. res = func()
  232. assert res[0] != 0
  233. def test_libc_load(self):
  234. import _rawffi
  235. _rawffi.get_libc()
  236. def test_getattr(self):
  237. import _rawffi
  238. libc = _rawffi.get_libc()
  239. func = libc.ptr('rand', [], 'i')
  240. assert libc.ptr('rand', [], 'i') is func # caching
  241. assert libc.ptr('rand', [], 'l') is not func
  242. assert isinstance(func, _rawffi.FuncPtr)
  243. raises(AttributeError, "libc.xxxxxxxxxxxxxx")
  244. def test_byordinal(self):
  245. if not self.iswin32:
  246. skip("win32 specific")
  247. import _rawffi
  248. lib = _rawffi.CDLL(self.lib_name)
  249. # This will call the ordinal function numbered 1
  250. # my compiler seems to order them alphabetically:
  251. # AAA_first_ordinal_function
  252. assert lib.ptr(1, [], 'i')()[0] == 42
  253. def test_getchar(self):
  254. import _rawffi
  255. lib = _rawffi.CDLL(self.lib_name)
  256. get_char = lib.ptr('get_char', ['P', 'H'], 'c')
  257. A = _rawffi.Array('c')
  258. B = _rawffi.Array('H')
  259. dupa = A(5, 'dupa')
  260. dupaptr = dupa.byptr()
  261. for i in range(4):
  262. intptr = B(1)
  263. intptr[0] = i
  264. res = get_char(dupaptr, intptr)
  265. assert res[0] == 'dupa'[i]
  266. intptr.free()
  267. dupaptr.free()
  268. dupa.free()
  269. def test_chararray_as_bytebuffer(self):
  270. # a useful extension to arrays of shape 'c': buffer-like slicing
  271. import _rawffi
  272. A = _rawffi.Array('c')
  273. buf = A(10, autofree=True)
  274. buf[0] = '*'
  275. assert buf[1:5] == '\x00' * 4
  276. buf[7:] = 'abc'
  277. assert buf[9] == 'c'
  278. assert buf[:8] == '*' + '\x00'*6 + 'a'
  279. def test_returning_str(self):
  280. import _rawffi
  281. lib = _rawffi.CDLL(self.lib_name)
  282. char_check = lib.ptr('char_check', ['c', 'c'], 's')
  283. A = _rawffi.Array('c')
  284. arg1 = A(1)
  285. arg2 = A(1)
  286. arg1[0] = 'y'
  287. arg2[0] = 'x'
  288. res = char_check(arg1, arg2)
  289. assert _rawffi.charp2string(res[0]) == 'xxxxxx'
  290. assert _rawffi.charp2rawstring(res[0]) == 'xxxxxx'
  291. assert _rawffi.charp2rawstring(res[0], 3) == 'xxx'
  292. a = A(6, 'xx\x00\x00xx')
  293. assert _rawffi.charp2string(a.buffer) == 'xx'
  294. assert _rawffi.charp2rawstring(a.buffer, 4) == 'xx\x00\x00'
  295. arg1[0] = 'x'
  296. arg2[0] = 'y'
  297. res = char_check(arg1, arg2)
  298. assert res[0] == 0
  299. assert _rawffi.charp2string(res[0]) is None
  300. arg1.free()
  301. arg2.free()
  302. a.free()
  303. def test_returning_unicode(self):
  304. import _rawffi
  305. A = _rawffi.Array('u')
  306. a = A(6, u'xx\x00\x00xx')
  307. res = _rawffi.wcharp2unicode(a.buffer)
  308. assert isinstance(res, unicode)
  309. assert res == u'xx'
  310. a.free()
  311. def test_rawstring2charp(self):
  312. import _rawffi
  313. A = _rawffi.Array('c')
  314. a = A(10, 'x'*10)
  315. _rawffi.rawstring2charp(a.buffer, "foobar")
  316. assert ''.join([a[i] for i in range(10)]) == "foobarxxxx"
  317. _rawffi.rawstring2charp(a.buffer, buffer("baz"))
  318. assert ''.join([a[i] for i in range(10)]) == "bazbarxxxx"
  319. a.free()
  320. def test_raw_callable(self):
  321. import _rawffi
  322. lib = _rawffi.CDLL(self.lib_name)
  323. get_raw_pointer = lib.ptr('get_raw_pointer', [], 'P')
  324. ptr = get_raw_pointer()
  325. rawcall = _rawffi.FuncPtr(ptr[0], ['h', 'h'], 'H')
  326. A = _rawffi.Array('h')
  327. arg1 = A(1)
  328. arg2 = A(1)
  329. arg1[0] = 1
  330. arg2[0] = 2
  331. res = rawcall(arg1, arg2)
  332. assert res[0] == 3
  333. arg1.free()
  334. arg2.free()
  335. assert rawcall.buffer == ptr[0]
  336. ptr = rawcall.byptr()
  337. assert ptr[0] == rawcall.buffer
  338. ptr.free()
  339. def test_raw_callable_returning_void(self):
  340. import _rawffi
  341. _rawffi.FuncPtr(0, [], None)
  342. # assert did not crash
  343. def test_short_addition(self):
  344. import _rawffi
  345. lib = _rawffi.CDLL(self.lib_name)
  346. short_add = lib.ptr('add_shorts', ['h', 'h'], 'H')
  347. A = _rawffi.Array('h')
  348. arg1 = A(1)
  349. arg2 = A(1)
  350. arg1[0] = 1
  351. arg2[0] = 2
  352. res = short_add(arg1, arg2)
  353. assert res[0] == 3
  354. arg1.free()
  355. arg2.free()
  356. def test_pow(self):
  357. import _rawffi
  358. libm = _rawffi.CDLL(self.libm_name)
  359. pow = libm.ptr('pow', ['d', 'd'], 'd')
  360. A = _rawffi.Array('d')
  361. arg1 = A(1)
  362. arg2 = A(1)
  363. raises(TypeError, "arg1[0] = 'x'")
  364. arg1[0] = 3
  365. arg2[0] = 2.0
  366. res = pow(arg1, arg2)
  367. assert res[0] == 9.0
  368. arg1.free()
  369. arg2.free()
  370. def test_time(self):
  371. import _rawffi
  372. libc = _rawffi.get_libc()
  373. try:
  374. time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test
  375. except AttributeError:
  376. # Since msvcr80, this function is named differently
  377. time = libc.ptr('_time32', ['z'], 'l')
  378. arg = _rawffi.Array('P')(1)
  379. arg[0] = 0
  380. res = time(arg)
  381. assert res[0] != 0
  382. arg.free()
  383. def test_gettimeofday(self):
  384. if self.iswin32:
  385. skip("No gettimeofday on win32")
  386. import _rawffi
  387. struct_type = _rawffi.Structure([('tv_sec', 'l'), ('tv_usec', 'l')])
  388. structure = struct_type()
  389. libc = _rawffi.get_libc()
  390. gettimeofday = libc.ptr('gettimeofday', ['P', 'P'], 'i')
  391. arg1 = structure.byptr()
  392. arg2 = _rawffi.Array('P')(1)
  393. res = gettimeofday(arg1, arg2)
  394. assert res[0] == 0
  395. struct2 = struct_type()
  396. arg1[0] = struct2
  397. res = gettimeofday(arg1, arg2)
  398. assert res[0] == 0
  399. assert structure.tv_usec != struct2.tv_usec
  400. assert (structure.tv_sec == struct2.tv_sec) or (structure.tv_sec == struct2.tv_sec - 1)
  401. raises(AttributeError, "structure.xxx")
  402. structure.free()
  403. struct2.free()
  404. arg1.free()
  405. arg2.free()
  406. def test_structreturn(self):
  407. import _rawffi
  408. X = _rawffi.Structure([('x', 'l')])
  409. x = X()
  410. x.x = 121
  411. Tm = _rawffi.Structure([('tm_sec', 'i'),
  412. ('tm_min', 'i'),
  413. ('tm_hour', 'i'),
  414. ("tm_mday", 'i'),
  415. ("tm_mon", 'i'),
  416. ("tm_year", 'i'),
  417. ("tm_wday", 'i'),
  418. ("tm_yday", 'i'),
  419. ("tm_isdst", 'i')])
  420. libc = _rawffi.get_libc()
  421. try:
  422. gmtime = libc.ptr('gmtime', ['P'], 'P')
  423. except AttributeError:
  424. # Since msvcr80, this function is named differently
  425. gmtime = libc.ptr('_gmtime32', ['P'], 'P')
  426. arg = x.byptr()
  427. res = gmtime(arg)
  428. t = Tm.fromaddress(res[0])
  429. arg.free()
  430. assert t.tm_year == 70
  431. assert t.tm_sec == 1
  432. assert t.tm_min == 2
  433. x.free()
  434. def test_nested_structures(self):
  435. import _rawffi
  436. lib = _rawffi.CDLL(self.lib_name)
  437. inner = lib.ptr("inner_struct_elem", ['P'], 'c')
  438. X = _rawffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')])
  439. next = X()
  440. next.next = 0
  441. next.x3 = 'x'
  442. x = X()
  443. x.next = next
  444. x.x1 = 1
  445. x.x2 = 2
  446. x.x3 = 'x'
  447. assert X.fromaddress(x.next).x3 == 'x'
  448. x.free()
  449. next.free()
  450. create_double_struct = lib.ptr("create_double_struct", [], 'P')
  451. res = create_double_struct()
  452. x = X.fromaddress(res[0])
  453. assert X.fromaddress(x.next).x2 == 3
  454. free_double_struct = lib.ptr("free_double_struct", ['P'], None)
  455. free_double_struct(res)
  456. def test_structure_bitfields_char(self):
  457. import _rawffi
  458. X = _rawffi.Structure([('A', 'B', 1),
  459. ('B', 'B', 6),
  460. ('C', 'B', 1)])
  461. x = X()
  462. x.A = 0xf
  463. x.B = 0xff
  464. x.C = 0xf
  465. assert x.A == 1
  466. assert x.B == 63
  467. assert x.C == 1
  468. x.free()
  469. def test_structure_bitfields_varied(self):
  470. import _rawffi
  471. X = _rawffi.Structure([('A', 'I', 1),
  472. ('B', 'I', 2),
  473. ('C', 'i', 2)])
  474. x = X()
  475. x.A = 0xf
  476. x.B = 0xf
  477. x.C = 0xf
  478. assert x.A == 1
  479. assert x.B == 3
  480. assert x.C == -1
  481. x.free()
  482. def test_structure_bitfields_int(self):
  483. import _rawffi
  484. Y = _rawffi.Structure([('a', 'i', 1),
  485. ('b', 'i', 30),
  486. ('c', 'i', 1)])
  487. y = Y()
  488. y.a, y.b, y.c = -1, -7, 1
  489. assert (y.a, y.b, y.c) == (-1, -7, -1)
  490. y.free()
  491. def test_structure_bitfields_uint(self):
  492. import _rawffi
  493. Y = _rawffi.Structure([('a', 'I', 1),
  494. ('b', 'I', 30),
  495. ('c', 'I', 1)])
  496. y = Y()
  497. y.a, y.b, y.c = 7, (1 << 29) | 1, 7
  498. assert (y.a, y.b, y.c) == (1, (1 << 29) | 1, 1)
  499. y.free()
  500. def test_structure_bitfields_longlong(self):
  501. import _rawffi
  502. Y = _rawffi.Structure([('a', 'q', 1),
  503. ('b', 'q', 62),
  504. ('c', 'q', 1)])
  505. y = Y()
  506. y.a, y.b, y.c = -1, -7, 1
  507. assert (y.a, y.b, y.c) == (-1, -7, -1)
  508. y.free()
  509. def test_structure_bitfields_ulonglong(self):
  510. import _rawffi
  511. Y = _rawffi.Structure([('a', 'Q', 1),
  512. ('b', 'Q', 62),
  513. ('c', 'Q', 1)])
  514. y = Y()
  515. y.a, y.b, y.c = 7, (1 << 61) | 1, 7
  516. assert (y.a, y.b, y.c) == (1, (1 << 61) | 1, 1)
  517. y.free()
  518. def test_structure_bitfields_single_signed(self):
  519. import _rawffi
  520. for s in [('i', 32), ('q', 64)]:
  521. Y = _rawffi.Structure([('a',) + s])
  522. y = Y()
  523. y.a = 10
  524. assert y.a == 10
  525. val = (1 << (s[1] - 1)) | 1
  526. y.a = val
  527. assert y.a == val - (1 << s[1])
  528. y.free()
  529. def test_structure_bitfields_single_unsigned(self):
  530. import _rawffi
  531. for s in [('I', 32), ('Q', 64)]:
  532. Y = _rawffi.Structure([('a',) + s])
  533. y = Y()
  534. y.a = 10
  535. assert y.a == 10
  536. val = (1 << (s[1] - 1)) | 1
  537. y.a = val
  538. assert y.a == val
  539. y.free()
  540. def test_invalid_bitfields(self):
  541. import _rawffi
  542. raises(TypeError, _rawffi.Structure, [('A', 'c', 1)])
  543. raises(ValueError, _rawffi.Structure, [('A', 'I', 129)])
  544. raises(ValueError, _rawffi.Structure, [('A', 'I', -1)])
  545. raises(ValueError, _rawffi.Structure, [('A', 'I', 0)])
  546. def test_packed_structure(self):
  547. import _rawffi
  548. Y = _rawffi.Structure([('a', 'c'),
  549. ('b', 'i')], pack=1)
  550. assert Y.size == 5
  551. def test_array(self):
  552. import _rawffi
  553. lib = _rawffi.CDLL(self.lib_name)
  554. A = _rawffi.Array('i')
  555. get_array_elem = lib.ptr('get_array_elem', ['P', 'i'], 'i')
  556. a = A(10)
  557. a[8] = 3
  558. a[7] = 1
  559. a[6] = 2
  560. arg1 = a.byptr()
  561. arg2 = A(1)
  562. for i, expected in enumerate([0, 0, 0, 0, 0, 0, 2, 1, 3, 0]):
  563. arg2[0] = i
  564. res = get_array_elem(arg1, arg2)
  565. assert res[0] == expected
  566. arg1.free()
  567. arg2.free()
  568. assert a[3] == 0
  569. a.free()
  570. def test_array_of_structure(self):
  571. import _rawffi
  572. lib = _rawffi.CDLL(self.lib_name)
  573. A = _rawffi.Array('P')
  574. X = _rawffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')])
  575. x = X()
  576. x.x2 = 3
  577. a = A(3)
  578. a[1] = x
  579. get_array_elem_s = lib.ptr('get_array_elem_s', ['P', 'i'], 'P')
  580. arg1 = a.byptr()
  581. arg2 = _rawffi.Array('i')(1)
  582. res = get_array_elem_s(arg1, arg2)
  583. assert res[0] == 0
  584. arg2[0] = 1
  585. res = get_array_elem_s(arg1, arg2)
  586. assert X.fromaddress(res[0]).x2 == 3
  587. assert res[0] == x.buffer
  588. arg1.free()
  589. arg2.free()
  590. x.free()
  591. a.free()
  592. def test_bad_parameters(self):
  593. import _rawffi
  594. lib = _rawffi.CDLL(self.lib_name)
  595. nothing = lib.ptr('nothing', [], None)
  596. assert nothing() is None
  597. raises(AttributeError, "lib.ptr('get_charx', [], None)")
  598. raises(ValueError, "lib.ptr('get_char', ['xx'], None)")
  599. raises(ValueError, "lib.ptr('get_char', ['x'], None)")
  600. raises(ValueError, "lib.ptr('get_char', [], 'x')")
  601. raises(ValueError, "_rawffi.Structure(['x1', 'xx'])")
  602. raises(ValueError, _rawffi.Structure, [('x1', 'xx')])
  603. raises(TypeError, _rawffi.Structure, [(u'\xe9', 'l')])
  604. raises(ValueError, "_rawffi.Array('xx')")
  605. def test_longs_ulongs(self):
  606. import _rawffi
  607. lib = _rawffi.CDLL(self.lib_name)
  608. some_huge_value = lib.ptr('some_huge_value', [], 'q')
  609. res = some_huge_value()
  610. assert res[0] == 1<<42
  611. some_huge_uvalue = lib.ptr('some_huge_uvalue', [], 'Q')
  612. res = some_huge_uvalue()
  613. assert res[0] == 1<<42
  614. pass_ll = lib.ptr('pass_ll', ['q'], 'q')
  615. arg1 = _rawffi.Array('q')(1)
  616. arg1[0] = 1<<42
  617. res = pass_ll(arg1)
  618. assert res[0] == 1<<42
  619. arg1.free()
  620. def test_callback(self):
  621. import _rawffi
  622. import struct
  623. libc = _rawffi.get_libc()
  624. ll_to_sort = _rawffi.Array('i')(4)
  625. for i in range(4):
  626. ll_to_sort[i] = 4-i
  627. qsort = libc.ptr('qsort', ['P', 'l', 'l', 'P'], None)
  628. bogus_args = []
  629. def compare(a, b):
  630. a1 = _rawffi.Array('i').fromaddress(_rawffi.Array('P').fromaddress(a, 1)[0], 1)
  631. a2 = _rawffi.Array('i').fromaddress(_rawffi.Array('P').fromaddress(b, 1)[0], 1)
  632. if a1[0] not in [1,2,3,4] or a2[0] not in [1,2,3,4]:
  633. bogus_args.append((a1[0], a2[0]))
  634. if a1[0] > a2[0]:
  635. return 1
  636. return -1
  637. a1 = ll_to_sort.byptr()
  638. a2 = _rawffi.Array('l')(1)
  639. a2[0] = len(ll_to_sort)
  640. a3 = _rawffi.Array('l')(1)
  641. a3[0] = struct.calcsize('i')
  642. cb = _rawffi.CallbackPtr(compare, ['P', 'P'], 'l')
  643. a4 = cb.byptr()
  644. qsort(a1, a2, a3, a4)
  645. res = [ll_to_sort[i] for i in range(len(ll_to_sort))]
  646. assert res == [1,2,3,4]
  647. assert not bogus_args
  648. a1.free()
  649. a2.free()
  650. a3.free()
  651. a4.free()
  652. ll_to_sort.free()
  653. cb.free()
  654. def test_another_callback(self):
  655. import _rawffi
  656. lib = _rawffi.CDLL(self.lib_name)
  657. runcallback = lib.ptr('runcallback', ['P'], 'q')
  658. def callback():
  659. return 1<<42
  660. cb = _rawffi.CallbackPtr(callback, [], 'q')
  661. a1 = cb.byptr()
  662. res = runcallback(a1)
  663. assert res[0] == 1<<42
  664. a1.free()
  665. cb.free()
  666. def test_void_returning_callback(self):
  667. import _rawffi
  668. lib = _rawffi.CDLL(self.lib_name)
  669. runcallback = lib.ptr('runcallback', ['P'], None)
  670. called = []
  671. def callback():
  672. called.append(True)
  673. cb = _rawffi.CallbackPtr(callback, [], None)
  674. a1 = cb.byptr()
  675. res = runcallback(a1)
  676. assert res is None
  677. assert called == [True]
  678. a1.free()
  679. cb.free()
  680. def test_raising_callback(self):
  681. import _rawffi, sys
  682. import StringIO
  683. lib = _rawffi.CDLL(self.lib_name)
  684. err = StringIO.StringIO()
  685. orig = sys.stderr
  686. sys.stderr = err
  687. try:
  688. runcallback = lib.ptr('runcallback', ['P'], 'q')
  689. def callback():
  690. 1/0
  691. cb = _rawffi.CallbackPtr(callback, [], 'q')
  692. a1 = cb.byptr()
  693. res = runcallback(a1)
  694. a1.free()
  695. cb.free()
  696. val = err.getvalue()
  697. assert 'ZeroDivisionError' in val
  698. assert 'callback' in val
  699. assert res[0] == 0L
  700. finally:
  701. sys.stderr = orig
  702. def test_setattr_struct(self):
  703. import _rawffi
  704. X = _rawffi.Structure([('value1', 'i'), ('value2', 'i')])
  705. x = X()
  706. x.value1 = 1
  707. x.value2 = 2
  708. assert x.value1 == 1
  709. assert x.value2 == 2
  710. x.value1 = 3
  711. assert x.value1 == 3
  712. raises(AttributeError, "x.foo")
  713. raises(AttributeError, "x.foo = 1")
  714. x.free()
  715. def test_sizes_and_alignments(self):
  716. import _rawffi
  717. for k, (s, a) in self.sizes_and_alignments.iteritems():
  718. print k,s,a
  719. assert _rawffi.sizeof(k) == s
  720. assert _rawffi.alignment(k) == a
  721. def test_unaligned(self):
  722. import _rawffi
  723. for k in self.float_typemap:
  724. S = _rawffi.Structure([('pad', 'c'), ('value', k)], pack=1)
  725. s = S()
  726. s.value = 4
  727. assert s.value == 4
  728. s.free()
  729. def test_array_addressof(self):
  730. import _rawffi
  731. lib = _rawffi.CDLL(self.lib_name)
  732. alloc = lib.ptr('allocate_array', [], 'P')
  733. A = _rawffi.Array('i')
  734. res = alloc()
  735. a = A.fromaddress(res[0], 1)
  736. assert a[0] == 3
  737. assert A.fromaddress(a.buffer, 1)[0] == 3
  738. def test_shape(self):
  739. import _rawffi
  740. A = _rawffi.Array('i')
  741. a = A(1)
  742. assert a.shape is A
  743. a.free()
  744. S = _rawffi.Structure([('v1', 'i')])
  745. s = S()
  746. s.v1 = 3
  747. assert s.shape is S
  748. s.free()
  749. def test_negative_pointers(self):
  750. import _rawffi
  751. A = _rawffi.Array('P')
  752. a = A(1)
  753. a[0] = -1234
  754. a.free()
  755. def test_long_with_fromaddress(self):
  756. import _rawffi
  757. addr = -1
  758. raises(ValueError, _rawffi.Array('u').fromaddress, addr, 100)
  759. def test_passing_raw_pointers(self):
  760. import _rawffi
  761. lib = _rawffi.CDLL(self.lib_name)
  762. A = _rawffi.Array('i')
  763. get_array_elem = lib.ptr('get_array_elem', ['P', 'i'], 'i')
  764. a = A(1)
  765. a[0] = 3
  766. arg1 = _rawffi.Array('P')(1)
  767. arg1[0] = a.buffer
  768. arg2 = _rawffi.Array('i')(1)
  769. res = get_array_elem(arg1, arg2)
  770. assert res[0] == 3
  771. arg1.free()
  772. arg2.free()
  773. a.free()
  774. def test_repr(self):
  775. import _rawffi, struct
  776. isize = struct.calcsize("i")
  777. lsize = struct.calcsize("l")
  778. assert (repr(_rawffi.Array('i')) ==
  779. "<_rawffi.Array 'i' (%d, %d)>" % (isize, isize))
  780. # fragile
  781. S = _rawffi.Structure([('x', 'c'), ('y', 'l')])
  782. assert (repr(_rawffi.Array((S, 2))) ==
  783. "<_rawffi.Array '\0' (%d, %d)>" % (4*lsize, lsize))
  784. assert (repr(_rawffi.Structure([('x', 'i'), ('yz', 'i')])) ==
  785. "<_rawffi.Structure 'x' 'yz' (%d, %d)>" % (2*isize, isize))
  786. s = _rawffi.Structure([('x', 'i'), ('yz', 'i')])()
  787. assert repr(s) == "<_rawffi struct %x>" % (s.buffer,)
  788. s.free()
  789. a = _rawffi.Array('i')(5)
  790. assert repr(a) == "<_rawffi array %x of length %d>" % (a.buffer,
  791. len(a))
  792. a.free()
  793. def test_wide_char(self):
  794. import _rawffi, sys
  795. A = _rawffi.Array('u')
  796. a = A(3)
  797. a[0] = u'x'
  798. a[1] = u'y'
  799. a[2] = u'z'
  800. assert a[0] == u'x'
  801. b = _rawffi.Array('c').fromaddress(a.buffer, 38)
  802. if sys.maxunicode > 65535:
  803. # UCS4 build
  804. if sys.byteorder == 'big':
  805. assert b[0] == '\x00'
  806. assert b[1] == '\x00'
  807. assert b[2] == '\x00'
  808. assert b[3] == 'x'
  809. assert b[4] == '\x00'
  810. assert b[5] == '\x00'
  811. assert b[6] == '\x00'
  812. assert b[7] == 'y'
  813. else:
  814. assert b[0] == 'x'
  815. assert b[1] == '\x00'
  816. assert b[2] == '\x00'
  817. assert b[3] == '\x00'
  818. assert b[4] == 'y'
  819. else:
  820. # UCS2 build
  821. assert b[0] == 'x'
  822. assert b[1] == '\x00'
  823. assert b[2] == 'y'
  824. a.free()
  825. def test_truncate(self):
  826. import _rawffi, struct
  827. a = _rawffi.Array('b')(1)
  828. a[0] = -5
  829. assert a[0] == -5
  830. a[0] = 123L
  831. assert a[0] == 123
  832. a[0] = 0x97817182ab128111111111111171817d042
  833. assert a[0] == 0x42
  834. a[0] = 255
  835. assert a[0] == -1
  836. a[0] = -2
  837. assert a[0] == -2
  838. a[0] = -255
  839. assert a[0] == 1
  840. a.free()
  841. a = _rawffi.Array('B')(1)
  842. a[0] = 123L
  843. assert a[0] == 123
  844. a[0] = 0x18329b1718b97d89b7198db817d042
  845. assert a[0] == 0x42
  846. a[0] = 255
  847. assert a[0] == 255
  848. a[0] = -2
  849. assert a[0] == 254
  850. a[0] = -255
  851. assert a[0] == 1
  852. a.free()
  853. a = _rawffi.Array('h')(1)
  854. a[0] = 123L
  855. assert a[0] == 123
  856. a[0] = 0x9112cbc91bd91db19aaaaaaaaaaaaaa8170d42
  857. assert a[0] == 0x0d42
  858. a[0] = 65535
  859. assert a[0] == -1
  860. a[0] = -2
  861. assert a[0] == -2
  862. a[0] = -65535
  863. assert a[0] == 1
  864. a.free()
  865. a = _rawffi.Array('H')(1)
  866. a[0] = 123L
  867. assert a[0] == 123
  868. a[0] = 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeee817d042
  869. assert a[0] == 0xd042
  870. a[0] = -2
  871. assert a[0] == 65534
  872. a.free()
  873. maxptr = (256 ** struct.calcsize("P")) - 1
  874. a = _rawffi.Array('P')(1)
  875. a[0] = 123L
  876. assert a[0] == 123
  877. a[0] = 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeee817d042
  878. assert a[0] == 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeee817d042 & maxptr
  879. a[0] = -2
  880. assert a[0] == maxptr - 1
  881. a.free()
  882. def test_getaddressindll(self):
  883. import _rawffi
  884. lib = _rawffi.CDLL(self.lib_name)
  885. def getprimitive(typecode, name):
  886. addr = lib.getaddressindll(name)
  887. return _rawffi.Array(typecode).fromaddress(addr, 1)
  888. a = getprimitive("l", "static_int")
  889. assert a[0] == 42
  890. a[0] = 43
  891. assert a[0] == 43
  892. a = getprimitive("d", "static_double")
  893. assert a[0] == 42.42
  894. a[0] = 43.43
  895. assert a[0] == 43.43
  896. a = getprimitive("g", "static_longdouble")
  897. assert a[0] == 42.42
  898. a[0] = 43.43
  899. assert a[0] == 43.43
  900. raises(ValueError, getprimitive, 'z', 'ddddddd')
  901. raises(ValueError, getprimitive, 'zzz', 'static_int')
  902. def test_segfault_exception(self):
  903. import _rawffi
  904. S = _rawffi.Structure([('x', 'i')])
  905. s = S()
  906. s.x = 3
  907. s.free()
  908. raises(_rawffi.SegfaultException, s.__getattr__, 'x')
  909. raises(_rawffi.SegfaultException, s.__setattr__, 'x', 3)
  910. A = _rawffi.Array('c')
  911. a = A(13)
  912. a.free()
  913. raises(_rawffi.SegfaultException, a.__getitem__, 3)
  914. raises(_rawffi.SegfaultException, a.__setitem__, 3, 3)
  915. def test_stackcheck(self):
  916. if self.platform != "msvc":
  917. skip("win32 msvc specific")
  918. # Even if the call corresponds to the specified signature,
  919. # the STDCALL calling convention may detect some errors
  920. import _rawffi
  921. lib = _rawffi.CDLL('kernel32')
  922. f = lib.ptr('SetLastError', [], 'i')
  923. try:
  924. f()
  925. except ValueError as e:
  926. assert "Procedure called with not enough arguments" in e.message
  927. else:
  928. assert 0, "Did not raise"
  929. f = lib.ptr('GetLastError', ['i'], None,
  930. flags=_rawffi.FUNCFLAG_STDCALL)
  931. arg = _rawffi.Array('i')(1)
  932. arg[0] = 1
  933. try:
  934. f(arg)
  935. except ValueError as e:
  936. assert "Procedure called with too many arguments" in e.message
  937. else:
  938. assert 0, "Did not raise"
  939. arg.free()
  940. def test_struct_byvalue(self):
  941. import _rawffi, sys
  942. X_Y = _rawffi.Structure([('x', 'l'), ('y', 'l')])
  943. x_y = X_Y()
  944. lib = _rawffi.CDLL(self.lib_name)
  945. print >> sys.stderr, "getting..."
  946. sum_x_y = lib.ptr('sum_x_y', [(X_Y, 1)], 'l')
  947. x_y.x = 200
  948. x_y.y = 220
  949. print >> sys.stderr, "calling..."
  950. res = sum_x_y(x_y)
  951. print >> sys.stderr, "done"
  952. assert res[0] == 420
  953. x_y.free()
  954. def test_callback_struct_byvalue(self):
  955. import _rawffi, sys
  956. X_Y = _rawffi.Structure([('x', 'l'), ('y', 'l')])
  957. lib = _rawffi.CDLL(self.lib_name)
  958. op_x_y = lib.ptr('op_x_y', [(X_Y, 1), 'P'], 'l')
  959. def callback(x_y):
  960. return x_y.x + x_y.y
  961. cb = _rawffi.CallbackPtr(callback, [(X_Y, 1)], 'l')
  962. x_y = X_Y()
  963. x_y.x = 200
  964. x_y.y = 220
  965. a1 = cb.byptr()
  966. res = op_x_y(x_y, a1)
  967. a1.free()
  968. x_y.free()
  969. cb.free()
  970. assert res[0] == 420
  971. def test_ret_struct(self):
  972. import _rawffi
  973. S2H = _rawffi.Structure([('x', 'h'), ('y', 'h')])
  974. s2h = S2H()
  975. lib = _rawffi.CDLL(self.lib_name)
  976. give = lib.ptr('give', ['h', 'h'], (S2H, 1))
  977. a1 = _rawffi.Array('h')(1)
  978. a2 = _rawffi.Array('h')(1)
  979. a1[0] = 13
  980. a2[0] = 17
  981. res = give(a1, a2)
  982. assert isinstance(res, _rawffi.StructureInstanceAutoFree)
  983. assert res.shape is S2H
  984. assert res.x == 13
  985. assert res.y == 17
  986. a1.free()
  987. a2.free()
  988. s2h.x = 7
  989. s2h.y = 11
  990. perturb = lib.ptr('perturb', [(S2H, 1)], (S2H, 1))
  991. res = perturb(s2h)
  992. assert isinstance(res, _rawffi.StructureInstanceAutoFree)
  993. assert res.shape is S2H
  994. assert res.x == 14
  995. assert res.y == 33
  996. assert s2h.x == 7
  997. assert s2h.y == 11
  998. s2h.free()
  999. def test_ret_struct_containing_array(self):
  1000. import _rawffi
  1001. AoI = _rawffi.Array('i')
  1002. S2A = _rawffi.Structure([('bah', (AoI, 2))])
  1003. lib = _rawffi.CDLL(self.lib_name)
  1004. get_s2a = lib.ptr('get_s2a', [], (S2A, 1))
  1005. check_s2a = lib.ptr('check_s2a', [(S2A, 1)], 'i')
  1006. res = get_s2a()
  1007. assert isinstance(res, _rawffi.StructureInstanceAutoFree)
  1008. assert res.shape is S2A
  1009. ok = check_s2a(res)
  1010. assert ok[0] == 1
  1011. def test_buffer(self):
  1012. import _rawffi
  1013. S = _rawffi.Structure((40, 1))
  1014. s = S(autofree=True)
  1015. b = buffer(s)
  1016. assert len(b) == 40
  1017. b[4] = b'X'
  1018. b[:3] = b'ABC'
  1019. assert b[:6] == b'ABC\x00X\x00'
  1020. A = _rawffi.Array('c')
  1021. a = A(10, autofree=True)
  1022. a[3] = b'x'
  1023. b = buffer(a)
  1024. assert len(b) == 10
  1025. assert b[3] == b'x'
  1026. b[6] = b'y'
  1027. assert a[6] == b'y'
  1028. b[3:5] = b'zt'
  1029. assert a[3] == b'z'
  1030. assert a[4] == b't'
  1031. b = memoryview(a)
  1032. assert len(b) == 10
  1033. assert b[3] == b'z'
  1034. b[3] = b'x'
  1035. assert b[3] == b'x'
  1036. def test_pypy_raw_address(self):
  1037. import _rawffi
  1038. S = _rawffi.Structure((40, 1))
  1039. s = S(autofree=True)
  1040. addr = buffer(s)._pypy_raw_address()
  1041. assert type(addr) is int
  1042. assert buffer(s)._pypy_raw_address() == addr
  1043. assert buffer(s, 10)._pypy_raw_address() == addr + 10
  1044. addr = memoryview(s)._pypy_raw_address()
  1045. assert type(addr) is int
  1046. assert memoryview(s)._pypy_raw_address() == addr
  1047. assert memoryview(s)[10:]._pypy_raw_address() == addr + 10
  1048. def test_union(self):
  1049. import _rawffi
  1050. longsize = _rawffi.sizeof('l')
  1051. S = _rawffi.Structure([('x', 'h'), ('y', 'l')], union=True)
  1052. s = S(autofree=False)
  1053. s.x = 12345
  1054. lib = _rawffi.CDLL(self.lib_name)
  1055. f = lib.ptr('ret_un_func', [(S, 1)], (S, 1))
  1056. ret = f(s)
  1057. assert ret.y == 1234500, "ret.y == %d" % (ret.y,)
  1058. s.free()
  1059. def test_ffi_type(self):
  1060. import _rawffi
  1061. EMPTY = _rawffi.Structure([])
  1062. S2E = _rawffi.Structure([('bah', (EMPTY, 1))])
  1063. S2E.get_ffi_type() # does not hang
  1064. def test_overflow_error(self):
  1065. import _rawffi
  1066. A = _rawffi.Array('d')
  1067. arg1 = A(1)
  1068. raises(OverflowError, "arg1[0] = 10**900")
  1069. arg1.free()
  1070. def test_errno(self):
  1071. import _rawffi
  1072. lib = _rawffi.CDLL(self.lib_name)
  1073. A = _rawffi.Array('i')
  1074. f = lib.ptr('check_errno', ['i'], 'i')
  1075. _rawffi.set_errno(42)
  1076. arg = A(1)
  1077. arg[0] = 43
  1078. res = f(arg)
  1079. assert res[0] == 42
  1080. z = _rawffi.get_errno()
  1081. assert z == 43
  1082. arg.free()
  1083. def test_last_error(self):
  1084. import sys
  1085. if sys.platform != 'win32':
  1086. skip("Windows test")
  1087. import _rawffi
  1088. lib = _rawffi.CDLL(self.lib_name)
  1089. A = _rawffi.Array('i')
  1090. f = lib.ptr('check_last_error', ['i'], 'i')
  1091. _rawffi.set_last_error(42)
  1092. arg = A(1)
  1093. arg[0] = 43
  1094. res = f(arg)
  1095. assert res[0] == 42
  1096. z = _rawffi.get_last_error()
  1097. assert z == 43
  1098. arg.free()
  1099. def test_cdll_name(self):
  1100. import _rawffi
  1101. lib = _rawffi.CDLL(self.lib_name)
  1102. assert lib.name == self.lib_name
  1103. class AppTestAutoFree:
  1104. spaceconfig = dict(usemodules=['_rawffi', 'struct'])
  1105. def setup_class(cls):
  1106. cls.w_sizes_and_alignments = cls.space.wrap(dict(
  1107. [(k, (v.c_size, v.c_alignment)) for k,v in TYPEMAP.iteritems()]))
  1108. Tracker.DO_TRACING = True
  1109. def test_structure_autofree(self):
  1110. import gc, _rawffi
  1111. gc.collect()
  1112. gc.collect()
  1113. S = _rawffi.Structure([('x', 'i')])
  1114. try:
  1115. oldnum = _rawffi._num_of_allocated_objects()
  1116. except RuntimeError:
  1117. oldnum = '?'
  1118. s = S(autofree=True)
  1119. s.x = 3
  1120. s = None
  1121. gc.collect()
  1122. if oldnum != '?':
  1123. assert oldnum == _rawffi._num_of_allocated_objects()
  1124. def test_array_autofree(self):
  1125. import gc, _rawffi
  1126. gc.collect()
  1127. try:
  1128. oldnum = _rawffi._num_of_allocated_objects()
  1129. except RuntimeError:
  1130. oldnum = '?'
  1131. A = _rawffi.Array('c')
  1132. a = A(6, 'xxyxx\x00', autofree=True)
  1133. assert _rawffi.charp2string(a.buffer) == 'xxyxx'
  1134. a = None
  1135. gc.collect()
  1136. if oldnum != '?':
  1137. assert oldnum == _rawffi._num_of_allocated_objects()
  1138. def teardown_class(cls):
  1139. Tracker.DO_TRACING = False