PageRenderTime 51ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/rpython/lltypesystem/test/test_ll2ctypes.py

https://bitbucket.org/pypy/pypy/
Python | 1402 lines | 1375 code | 19 blank | 8 comment | 1 complexity | fea8977678574ed203f766d02d174e74 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. import py
  2. import sys, struct
  3. import ctypes
  4. from pypy.rpython.lltypesystem import lltype, rffi, llmemory
  5. from pypy.rpython.tool import rffi_platform
  6. from pypy.rpython.lltypesystem.ll2ctypes import lltype2ctypes, ctypes2lltype
  7. from pypy.rpython.lltypesystem.ll2ctypes import standard_c_lib
  8. from pypy.rpython.lltypesystem.ll2ctypes import uninitialized2ctypes
  9. from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED, force_cast
  10. from pypy.rpython.lltypesystem.ll2ctypes import cast_adr_to_int, get_ctypes_type
  11. from pypy.rpython.lltypesystem.ll2ctypes import _llgcopaque
  12. from pypy.rpython.annlowlevel import llhelper
  13. from pypy.rlib import rposix
  14. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  15. from pypy.tool.udir import udir
  16. from pypy.rpython.test.test_llinterp import interpret
  17. from pypy.annotation.annrpython import RPythonAnnotator
  18. from pypy.rpython.rtyper import RPythonTyper
  19. if False: # for now, please keep it False by default
  20. from pypy.rpython.lltypesystem import ll2ctypes
  21. ll2ctypes.do_allocation_in_far_regions()
  22. class TestLL2Ctypes(object):
  23. def setup_method(self, meth):
  24. ALLOCATED.clear()
  25. def test_primitive(self):
  26. assert lltype2ctypes(5) == 5
  27. assert lltype2ctypes('?') == ord('?')
  28. assert lltype2ctypes('\xE0') == 0xE0
  29. assert lltype2ctypes(unichr(1234)) == 1234
  30. assert ctypes2lltype(lltype.Signed, 5) == 5
  31. assert ctypes2lltype(lltype.Char, ord('a')) == 'a'
  32. assert ctypes2lltype(lltype.UniChar, ord(u'x')) == u'x'
  33. assert ctypes2lltype(lltype.Char, 0xFF) == '\xFF'
  34. assert lltype2ctypes(5.25) == 5.25
  35. assert ctypes2lltype(lltype.Float, 5.25) == 5.25
  36. assert lltype2ctypes(u'x') == ord(u'x')
  37. res = lltype2ctypes(rffi.r_singlefloat(-3.5))
  38. assert isinstance(res, ctypes.c_float)
  39. assert res.value == -3.5
  40. res = ctypes2lltype(lltype.SingleFloat, ctypes.c_float(-3.5))
  41. assert isinstance(res, rffi.r_singlefloat)
  42. assert float(res) == -3.5
  43. assert lltype2ctypes(rffi.r_ulong(-1)) == sys.maxint * 2 + 1
  44. res = ctypes2lltype(lltype.Unsigned, sys.maxint * 2 + 1)
  45. assert (res, type(res)) == (rffi.r_ulong(-1), rffi.r_ulong)
  46. assert ctypes2lltype(lltype.Bool, 0) is False
  47. assert ctypes2lltype(lltype.Bool, 1) is True
  48. res = lltype2ctypes(llmemory.sizeof(lltype.Signed))
  49. assert res == struct.calcsize("l")
  50. S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
  51. res = lltype2ctypes(llmemory.sizeof(S))
  52. assert res == struct.calcsize("ll")
  53. p = lltype.nullptr(S)
  54. cptr = lltype2ctypes(p)
  55. assert not cptr
  56. py.test.raises(ValueError, 'cptr.contents') # NULL pointer access
  57. res = ctypes2lltype(lltype.Ptr(S), cptr)
  58. assert res == p
  59. assert not ALLOCATED # detects memory leaks in the test
  60. def test_simple_struct(self):
  61. S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
  62. s = lltype.malloc(S, flavor='raw')
  63. s.x = 123
  64. sc = lltype2ctypes(s)
  65. assert isinstance(sc.contents, ctypes.Structure)
  66. assert sc.contents.x == 123
  67. sc.contents.x = 456
  68. assert s.x == 456
  69. s.x = 789
  70. assert sc.contents.x == 789
  71. s.y = 52
  72. assert sc.contents.y == 52
  73. lltype.free(s, flavor='raw')
  74. assert not ALLOCATED # detects memory leaks in the test
  75. def test_get_pointer(self):
  76. # Equivalent of the C code::
  77. # struct S1 { struct S2 *ptr; struct S2 buf; };
  78. # struct S1 s1;
  79. # s1.ptr = & s1.buf;
  80. S2 = lltype.Struct('S2', ('y', lltype.Signed))
  81. S1 = lltype.Struct('S',
  82. ('sub', lltype.Struct('SUB',
  83. ('ptr', lltype.Ptr(S2)))),
  84. ('ptr', lltype.Ptr(S2)),
  85. ('buf', S2), # Works when this field is first!
  86. )
  87. s1 = lltype.malloc(S1, flavor='raw')
  88. s1.ptr = s1.buf
  89. s1.sub.ptr = s1.buf
  90. x = rffi.cast(rffi.CCHARP, s1)
  91. lltype.free(s1, flavor='raw')
  92. def test_struct_ptrs(self):
  93. S2 = lltype.Struct('S2', ('y', lltype.Signed))
  94. S1 = lltype.Struct('S', ('x', lltype.Signed), ('p', lltype.Ptr(S2)))
  95. s1 = lltype.malloc(S1, flavor='raw')
  96. s2a = lltype.malloc(S2, flavor='raw')
  97. s2b = lltype.malloc(S2, flavor='raw')
  98. s2a.y = ord('a')
  99. s2b.y = ord('b')
  100. sc1 = lltype2ctypes(s1)
  101. sc1.contents.x = 50
  102. assert s1.x == 50
  103. sc1.contents.p = lltype2ctypes(s2a)
  104. assert s1.p == s2a
  105. s1.p.y -= 32
  106. assert sc1.contents.p.contents.y == ord('A')
  107. s1.p = s2b
  108. sc1.contents.p.contents.y -= 32
  109. assert s2b.y == ord('B')
  110. lltype.free(s1, flavor='raw')
  111. lltype.free(s2a, flavor='raw')
  112. lltype.free(s2b, flavor='raw')
  113. assert not ALLOCATED # detects memory leaks in the test
  114. def test_simple_array(self):
  115. A = lltype.Array(lltype.Signed)
  116. a = lltype.malloc(A, 10, flavor='raw')
  117. a[0] = 100
  118. a[1] = 101
  119. a[2] = 102
  120. ac = lltype2ctypes(a, normalize=False)
  121. assert isinstance(ac.contents, ctypes.Structure)
  122. assert ac.contents.length == 10
  123. assert ac.contents._fields_[0] == ('length', ctypes.c_long)
  124. assert ac.contents.items[1] == 101
  125. ac.contents.items[2] = 456
  126. assert a[2] == 456
  127. a[3] = 789
  128. assert ac.contents.items[3] == 789
  129. lltype.free(a, flavor='raw')
  130. assert not ALLOCATED # detects memory leaks in the test
  131. def test_array_inside_struct(self):
  132. # like rstr.STR, but not Gc
  133. STR = lltype.Struct('STR', ('x', lltype.Signed), ('y', lltype.Array(lltype.Char)))
  134. a = lltype.malloc(STR, 3, flavor='raw')
  135. a.y[0] = 'x'
  136. a.y[1] = 'y'
  137. a.y[2] = 'z'
  138. # we need to pass normalize=False, otherwise 'ac' is returned of
  139. # a normalized standard type, which complains about IndexError
  140. # when doing 'ac.contents.y.items[2]'.
  141. ac = lltype2ctypes(a, normalize=False)
  142. assert ac.contents.y.length == 3
  143. assert ac.contents.y.items[2] == ord('z')
  144. lltype.free(a, flavor='raw')
  145. assert not ALLOCATED
  146. def test_array_nolength(self):
  147. A = lltype.Array(lltype.Signed, hints={'nolength': True})
  148. a = lltype.malloc(A, 10, flavor='raw')
  149. a[0] = 100
  150. a[1] = 101
  151. a[2] = 102
  152. ac = lltype2ctypes(a, normalize=False)
  153. assert isinstance(ac.contents, ctypes.Structure)
  154. assert ac.contents.items[1] == 101
  155. ac.contents.items[2] = 456
  156. assert a[2] == 456
  157. a[3] = 789
  158. assert ac.contents.items[3] == 789
  159. assert ctypes.sizeof(ac.contents) == 10 * ctypes.sizeof(ctypes.c_long)
  160. lltype.free(a, flavor='raw')
  161. assert not ALLOCATED # detects memory leaks in the test
  162. def test_charp(self):
  163. s = rffi.str2charp("hello")
  164. sc = lltype2ctypes(s, normalize=False)
  165. assert sc.contents.items[0] == ord('h')
  166. assert sc.contents.items[1] == ord('e')
  167. assert sc.contents.items[2] == ord('l')
  168. assert sc.contents.items[3] == ord('l')
  169. assert sc.contents.items[4] == ord('o')
  170. assert sc.contents.items[5] == 0
  171. assert not hasattr(sc.contents, 'length')
  172. sc.contents.items[1] = ord('E')
  173. assert s[1] == 'E'
  174. s[0] = 'H'
  175. assert sc.contents.items[0] == ord('H')
  176. rffi.free_charp(s)
  177. assert not ALLOCATED # detects memory leaks in the test
  178. def test_unicharp(self):
  179. SP = rffi.CArrayPtr(lltype.UniChar)
  180. s = lltype.malloc(SP.TO, 4, flavor='raw')
  181. s[0] = u'x'
  182. s[1] = u'y'
  183. s[2] = u'z'
  184. s[3] = u'\x00'
  185. sc = lltype2ctypes(s, normalize=False)
  186. assert sc.contents.items[0] == ord(u'x')
  187. assert sc.contents.items[1] == ord(u'y')
  188. assert sc.contents.items[2] == ord(u'z')
  189. assert not hasattr(sc.contents, 'length')
  190. lltype.free(s, flavor='raw')
  191. assert not ALLOCATED
  192. def test_strlen(self):
  193. eci = ExternalCompilationInfo(includes=['string.h'])
  194. strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T,
  195. compilation_info=eci)
  196. s = rffi.str2charp("xxx")
  197. res = strlen(s)
  198. rffi.free_charp(s)
  199. assert res == 3 # actually r_size_t(3)
  200. s = rffi.str2charp("")
  201. res = strlen(s)
  202. rffi.free_charp(s)
  203. assert res == 0 # actually r_size_t(0)
  204. assert not ALLOCATED # detects memory leaks in the test
  205. def test_func_not_in_clib(self):
  206. eci = ExternalCompilationInfo(libraries=['m'])
  207. foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed)
  208. py.test.raises(NotImplementedError, foobar)
  209. foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed,
  210. compilation_info=eci) # math library
  211. py.test.raises(NotImplementedError, foobar)
  212. eci = ExternalCompilationInfo(libraries=['m', 'z'])
  213. foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed,
  214. compilation_info=eci) # math and zlib
  215. py.test.raises(NotImplementedError, foobar)
  216. eci = ExternalCompilationInfo(libraries=['I_really_dont_exist_either'])
  217. foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed,
  218. compilation_info=eci)
  219. py.test.raises(NotImplementedError, foobar)
  220. assert not ALLOCATED # detects memory leaks in the test
  221. def test_cstruct_to_ll(self):
  222. S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
  223. s = lltype.malloc(S, flavor='raw')
  224. s2 = lltype.malloc(S, flavor='raw')
  225. s.x = 123
  226. sc = lltype2ctypes(s)
  227. t = ctypes2lltype(lltype.Ptr(S), sc)
  228. assert lltype.typeOf(t) == lltype.Ptr(S)
  229. assert s == t
  230. assert not (s != t)
  231. assert t == s
  232. assert not (t != s)
  233. assert t != lltype.nullptr(S)
  234. assert not (t == lltype.nullptr(S))
  235. assert lltype.nullptr(S) != t
  236. assert not (lltype.nullptr(S) == t)
  237. assert t != s2
  238. assert not (t == s2)
  239. assert s2 != t
  240. assert not (s2 == t)
  241. assert t.x == 123
  242. t.x += 1
  243. assert s.x == 124
  244. s.x += 1
  245. assert t.x == 125
  246. lltype.free(s, flavor='raw')
  247. lltype.free(s2, flavor='raw')
  248. assert not ALLOCATED # detects memory leaks in the test
  249. def test_carray_to_ll(self):
  250. A = lltype.Array(lltype.Signed, hints={'nolength': True})
  251. a = lltype.malloc(A, 10, flavor='raw')
  252. a2 = lltype.malloc(A, 10, flavor='raw')
  253. a[0] = 100
  254. a[1] = 101
  255. a[2] = 110
  256. ac = lltype2ctypes(a)
  257. b = ctypes2lltype(lltype.Ptr(A), ac)
  258. assert lltype.typeOf(b) == lltype.Ptr(A)
  259. assert b == a
  260. assert not (b != a)
  261. assert a == b
  262. assert not (a != b)
  263. assert b != lltype.nullptr(A)
  264. assert not (b == lltype.nullptr(A))
  265. assert lltype.nullptr(A) != b
  266. assert not (lltype.nullptr(A) == b)
  267. assert b != a2
  268. assert not (b == a2)
  269. assert a2 != b
  270. assert not (a2 == b)
  271. assert b[2] == 110
  272. b[2] *= 2
  273. assert a[2] == 220
  274. a[2] *= 3
  275. assert b[2] == 660
  276. lltype.free(a, flavor='raw')
  277. lltype.free(a2, flavor='raw')
  278. assert not ALLOCATED # detects memory leaks in the test
  279. def test_strchr(self):
  280. eci = ExternalCompilationInfo(includes=['string.h'])
  281. strchr = rffi.llexternal('strchr', [rffi.CCHARP, rffi.INT],
  282. rffi.CCHARP, compilation_info=eci)
  283. s = rffi.str2charp("hello world")
  284. res = strchr(s, ord('r'))
  285. assert res[0] == 'r'
  286. assert res[1] == 'l'
  287. assert res[2] == 'd'
  288. assert res[3] == '\x00'
  289. # XXX maybe we should also allow res[-1], res[-2]...
  290. rffi.free_charp(s)
  291. assert not ALLOCATED # detects memory leaks in the test
  292. def test_frexp(self):
  293. if sys.platform != 'win32':
  294. eci = ExternalCompilationInfo(includes=['math.h'],
  295. libraries=['m'])
  296. else:
  297. eci = ExternalCompilationInfo(includes=['math.h'])
  298. A = lltype.FixedSizeArray(rffi.INT, 1)
  299. frexp = rffi.llexternal('frexp', [rffi.DOUBLE, lltype.Ptr(A)],
  300. rffi.DOUBLE, compilation_info=eci)
  301. p = lltype.malloc(A, flavor='raw')
  302. res = frexp(2.5, p)
  303. assert res == 0.625
  304. assert p[0] == 2
  305. lltype.free(p, flavor='raw')
  306. assert not ALLOCATED # detects memory leaks in the test
  307. def test_rand(self):
  308. eci = ExternalCompilationInfo(includes=['stdlib.h'])
  309. rand = rffi.llexternal('rand', [], rffi.INT,
  310. compilation_info=eci)
  311. srand = rffi.llexternal('srand', [rffi.UINT], lltype.Void,
  312. compilation_info=eci)
  313. srand(rffi.r_uint(123))
  314. res1 = rand()
  315. res2 = rand()
  316. res3 = rand()
  317. srand(rffi.r_uint(123))
  318. res1b = rand()
  319. res2b = rand()
  320. res3b = rand()
  321. assert res1 == res1b
  322. assert res2 == res2b
  323. assert res3 == res3b
  324. assert not ALLOCATED # detects memory leaks in the test
  325. def test_opaque_obj(self):
  326. if sys.platform == 'win32':
  327. py.test.skip("No gettimeofday on win32")
  328. eci = ExternalCompilationInfo(
  329. includes = ['sys/time.h', 'time.h']
  330. )
  331. TIMEVALP = rffi.COpaquePtr('struct timeval', compilation_info=eci)
  332. TIMEZONEP = rffi.COpaquePtr('struct timezone', compilation_info=eci)
  333. gettimeofday = rffi.llexternal('gettimeofday', [TIMEVALP, TIMEZONEP],
  334. rffi.INT, compilation_info=eci)
  335. ll_timevalp = lltype.malloc(TIMEVALP.TO, flavor='raw')
  336. ll_timezonep = lltype.malloc(TIMEZONEP.TO, flavor='raw')
  337. res = gettimeofday(ll_timevalp, ll_timezonep)
  338. assert res != -1
  339. lltype.free(ll_timezonep, flavor='raw')
  340. lltype.free(ll_timevalp, flavor='raw')
  341. assert not ALLOCATED # detects memory leaks in the test
  342. def test_opaque_obj_2(self):
  343. FILEP = rffi.COpaquePtr('FILE')
  344. fopen = rffi.llexternal('fopen', [rffi.CCHARP, rffi.CCHARP], FILEP)
  345. fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
  346. tmppath = udir.join('test_ll2ctypes.test_opaque_obj_2')
  347. ll_file = fopen(str(tmppath), "w")
  348. assert ll_file
  349. fclose(ll_file)
  350. assert tmppath.check(file=1)
  351. assert not ALLOCATED # detects memory leaks in the test
  352. assert rffi.cast(FILEP, -1) == rffi.cast(FILEP, -1)
  353. def test_simple_cast(self):
  354. assert rffi.cast(rffi.SIGNEDCHAR, 0x123456) == 0x56
  355. assert rffi.cast(rffi.SIGNEDCHAR, 0x123481) == -127
  356. assert rffi.cast(rffi.CHAR, 0x123456) == '\x56'
  357. assert rffi.cast(rffi.CHAR, 0x123481) == '\x81'
  358. assert rffi.cast(rffi.UCHAR, 0x123481) == 0x81
  359. assert not ALLOCATED # detects memory leaks in the test
  360. def test_forced_ptr_cast(self):
  361. import array
  362. A = lltype.Array(lltype.Signed, hints={'nolength': True})
  363. B = lltype.Array(lltype.Char, hints={'nolength': True})
  364. a = lltype.malloc(A, 10, flavor='raw')
  365. for i in range(10):
  366. a[i] = i*i
  367. b = rffi.cast(lltype.Ptr(B), a)
  368. checker = array.array('l')
  369. for i in range(10):
  370. checker.append(i*i)
  371. expected = checker.tostring()
  372. for i in range(len(expected)):
  373. assert b[i] == expected[i]
  374. c = rffi.cast(rffi.VOIDP, a)
  375. addr = lltype2ctypes(c)
  376. #assert addr == ctypes.addressof(a._obj._ctypes_storage)
  377. d = ctypes2lltype(rffi.VOIDP, addr)
  378. assert lltype.typeOf(d) == rffi.VOIDP
  379. assert c == d
  380. e = rffi.cast(lltype.Ptr(A), d)
  381. for i in range(10):
  382. assert e[i] == i*i
  383. c = lltype.nullptr(rffi.VOIDP.TO)
  384. addr = rffi.cast(lltype.Signed, c)
  385. assert addr == 0
  386. lltype.free(a, flavor='raw')
  387. assert not ALLOCATED # detects memory leaks in the test
  388. def test_adr_cast(self):
  389. from pypy.rpython.annlowlevel import llstr
  390. from pypy.rpython.lltypesystem.rstr import STR
  391. P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1))
  392. def f():
  393. a = llstr("xyz")
  394. b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars')
  395. + llmemory.itemoffsetof(STR.chars, 0))
  396. buf = rffi.cast(rffi.VOIDP, b)
  397. return buf[2]
  398. assert f() == 'z'
  399. res = interpret(f, [])
  400. assert res == 'z'
  401. def test_funcptr1(self):
  402. def dummy(n):
  403. return n+1
  404. FUNCTYPE = lltype.FuncType([lltype.Signed], lltype.Signed)
  405. cdummy = lltype2ctypes(llhelper(lltype.Ptr(FUNCTYPE), dummy))
  406. assert isinstance(cdummy,
  407. ctypes.CFUNCTYPE(ctypes.c_long, ctypes.c_long))
  408. res = cdummy(41)
  409. assert res == 42
  410. lldummy = ctypes2lltype(lltype.Ptr(FUNCTYPE), cdummy)
  411. assert lltype.typeOf(lldummy) == lltype.Ptr(FUNCTYPE)
  412. res = lldummy(41)
  413. assert res == 42
  414. assert not ALLOCATED # detects memory leaks in the test
  415. def test_funcptr2(self):
  416. FUNCTYPE = lltype.FuncType([rffi.CCHARP], lltype.Signed)
  417. cstrlen = standard_c_lib.strlen
  418. llstrlen = ctypes2lltype(lltype.Ptr(FUNCTYPE), cstrlen)
  419. assert lltype.typeOf(llstrlen) == lltype.Ptr(FUNCTYPE)
  420. p = rffi.str2charp("hi there")
  421. res = llstrlen(p)
  422. assert res == 8
  423. cstrlen2 = lltype2ctypes(llstrlen)
  424. cp = lltype2ctypes(p)
  425. assert cstrlen2.restype == ctypes.c_long
  426. res = cstrlen2(cp)
  427. assert res == 8
  428. rffi.free_charp(p)
  429. assert not ALLOCATED # detects memory leaks in the test
  430. def test_funcptr_cast(self):
  431. eci = ExternalCompilationInfo(
  432. separate_module_sources=["""
  433. long mul(long x, long y) { return x*y; }
  434. long(*get_mul(long x)) () { return &mul; }
  435. """],
  436. export_symbols=['get_mul'])
  437. get_mul = rffi.llexternal(
  438. 'get_mul', [],
  439. lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)),
  440. compilation_info=eci)
  441. # This call returns a pointer to a function taking one argument
  442. funcptr = get_mul()
  443. # cast it to the "real" function type
  444. FUNCTYPE2 = lltype.FuncType([lltype.Signed, lltype.Signed],
  445. lltype.Signed)
  446. cmul = rffi.cast(lltype.Ptr(FUNCTYPE2), funcptr)
  447. # and it can be called with the expected number of arguments
  448. res = cmul(41, 42)
  449. assert res == 41 * 42
  450. raises(TypeError, cmul, 41)
  451. raises(TypeError, cmul, 41, 42, 43)
  452. def test_qsort(self):
  453. CMPFUNC = lltype.FuncType([rffi.VOIDP, rffi.VOIDP], rffi.INT)
  454. qsort = rffi.llexternal('qsort', [rffi.VOIDP,
  455. rffi.SIZE_T,
  456. rffi.SIZE_T,
  457. lltype.Ptr(CMPFUNC)],
  458. lltype.Void)
  459. lst = [23, 43, 24, 324, 242, 34, 78, 5, 3, 10]
  460. A = lltype.Array(lltype.Signed, hints={'nolength': True})
  461. a = lltype.malloc(A, 10, flavor='raw')
  462. for i in range(10):
  463. a[i] = lst[i]
  464. SIGNEDPTR = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1))
  465. def my_compar(p1, p2):
  466. p1 = rffi.cast(SIGNEDPTR, p1)
  467. p2 = rffi.cast(SIGNEDPTR, p2)
  468. print 'my_compar:', p1[0], p2[0]
  469. return rffi.cast(rffi.INT, cmp(p1[0], p2[0]))
  470. qsort(rffi.cast(rffi.VOIDP, a),
  471. rffi.cast(rffi.SIZE_T, 10),
  472. rffi.cast(rffi.SIZE_T, llmemory.sizeof(lltype.Signed)),
  473. llhelper(lltype.Ptr(CMPFUNC), my_compar))
  474. for i in range(10):
  475. print a[i],
  476. print
  477. lst.sort()
  478. for i in range(10):
  479. assert a[i] == lst[i]
  480. lltype.free(a, flavor='raw')
  481. assert not ALLOCATED # detects memory leaks in the test
  482. # def test_signal(self):...
  483. def test_uninitialized2ctypes(self):
  484. # for now, uninitialized fields are filled with 0xDD in the ctypes data
  485. def checkobj(o, size):
  486. p = ctypes.cast(ctypes.c_void_p(ctypes.addressof(o)),
  487. ctypes.POINTER(ctypes.c_ubyte*size))
  488. for i in range(size):
  489. assert p.contents[i] == 0xDD
  490. def checkval(v, fmt):
  491. res = struct.pack(fmt, v)
  492. assert res == "\xDD" * len(res)
  493. checkval(uninitialized2ctypes(rffi.CHAR), 'B')
  494. checkval(uninitialized2ctypes(rffi.SHORT), 'h')
  495. checkval(uninitialized2ctypes(rffi.INT), 'i')
  496. checkval(uninitialized2ctypes(rffi.UINT), 'I')
  497. checkval(uninitialized2ctypes(rffi.LONGLONG), 'q')
  498. checkval(uninitialized2ctypes(rffi.DOUBLE), 'd')
  499. checkobj(uninitialized2ctypes(rffi.INTP),
  500. ctypes.sizeof(ctypes.c_void_p))
  501. checkobj(uninitialized2ctypes(rffi.CCHARP),
  502. ctypes.sizeof(ctypes.c_void_p))
  503. S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
  504. s = lltype.malloc(S, flavor='raw')
  505. sc = lltype2ctypes(s)
  506. checkval(sc.contents.x, 'l')
  507. checkval(sc.contents.y, 'l')
  508. lltype.free(s, flavor='raw')
  509. assert not ALLOCATED # detects memory leaks in the test
  510. def test_substructures(self):
  511. S1 = lltype.Struct('S1', ('x', lltype.Signed))
  512. BIG = lltype.Struct('BIG', ('s1a', S1), ('s1b', S1))
  513. s = lltype.malloc(BIG, flavor='raw')
  514. s.s1a.x = 123
  515. s.s1b.x = 456
  516. sc = lltype2ctypes(s)
  517. assert sc.contents.s1a.x == 123
  518. assert sc.contents.s1b.x == 456
  519. sc.contents.s1a.x += 1
  520. sc.contents.s1b.x += 10
  521. assert s.s1a.x == 124
  522. assert s.s1b.x == 466
  523. s.s1a.x += 3
  524. s.s1b.x += 30
  525. assert sc.contents.s1a.x == 127
  526. assert sc.contents.s1b.x == 496
  527. lltype.free(s, flavor='raw')
  528. s = lltype.malloc(BIG, flavor='raw')
  529. s1ac = lltype2ctypes(s.s1a)
  530. s1ac.contents.x = 53
  531. sc = lltype2ctypes(s)
  532. assert sc.contents.s1a.x == 53
  533. sc.contents.s1a.x += 1
  534. assert s1ac.contents.x == 54
  535. assert s.s1a.x == 54
  536. s.s1a.x += 2
  537. assert s1ac.contents.x == 56
  538. assert sc.contents.s1a.x == 56
  539. sc.contents.s1a.x += 3
  540. assert s1ac.contents.x == 59
  541. assert s.s1a.x == 59
  542. t = ctypes2lltype(lltype.Ptr(BIG), sc)
  543. assert t == s
  544. assert t.s1a == s.s1a
  545. assert t.s1a.x == 59
  546. s.s1b.x = 8888
  547. assert t.s1b == s.s1b
  548. assert t.s1b.x == 8888
  549. t1 = ctypes2lltype(lltype.Ptr(S1), s1ac)
  550. assert t.s1a == t1
  551. assert t1.x == 59
  552. t1.x += 1
  553. assert sc.contents.s1a.x == 60
  554. lltype.free(s, flavor='raw')
  555. assert not ALLOCATED # detects memory leaks in the test
  556. def test_recursive_struct(self):
  557. SX = lltype.ForwardReference()
  558. S1 = lltype.Struct('S1', ('p', lltype.Ptr(SX)), ('x', lltype.Signed))
  559. SX.become(S1)
  560. # a chained list
  561. s1 = lltype.malloc(S1, flavor='raw')
  562. s2 = lltype.malloc(S1, flavor='raw')
  563. s3 = lltype.malloc(S1, flavor='raw')
  564. s1.x = 111
  565. s2.x = 222
  566. s3.x = 333
  567. s1.p = s2
  568. s2.p = s3
  569. s3.p = lltype.nullptr(S1)
  570. sc1 = lltype2ctypes(s1)
  571. sc2 = sc1.contents.p
  572. sc3 = sc2.contents.p
  573. assert not sc3.contents.p
  574. assert sc1.contents.x == 111
  575. assert sc2.contents.x == 222
  576. assert sc3.contents.x == 333
  577. sc3.contents.x += 1
  578. assert s3.x == 334
  579. s3.x += 2
  580. assert sc3.contents.x == 336
  581. lltype.free(s1, flavor='raw')
  582. lltype.free(s2, flavor='raw')
  583. lltype.free(s3, flavor='raw')
  584. # a self-cycle
  585. s1 = lltype.malloc(S1, flavor='raw')
  586. s1.x = 12
  587. s1.p = s1
  588. sc1 = lltype2ctypes(s1)
  589. assert sc1.contents.x == 12
  590. assert (ctypes.addressof(sc1.contents.p.contents) ==
  591. ctypes.addressof(sc1.contents))
  592. s1.x *= 5
  593. assert sc1.contents.p.contents.p.contents.p.contents.x == 60
  594. lltype.free(s1, flavor='raw')
  595. # a longer cycle
  596. s1 = lltype.malloc(S1, flavor='raw')
  597. s2 = lltype.malloc(S1, flavor='raw')
  598. s1.x = 111
  599. s1.p = s2
  600. s2.x = 222
  601. s2.p = s1
  602. sc1 = lltype2ctypes(s1)
  603. assert sc1.contents.x == 111
  604. assert sc1.contents.p.contents.x == 222
  605. assert (ctypes.addressof(sc1.contents.p.contents) !=
  606. ctypes.addressof(sc1.contents))
  607. assert (ctypes.addressof(sc1.contents.p.contents.p.contents) ==
  608. ctypes.addressof(sc1.contents))
  609. lltype.free(s1, flavor='raw')
  610. lltype.free(s2, flavor='raw')
  611. assert not ALLOCATED # detects memory leaks in the test
  612. def test_indirect_recursive_struct(self):
  613. S2Forward = lltype.ForwardReference()
  614. S1 = lltype.Struct('S1', ('p', lltype.Ptr(S2Forward)))
  615. A2 = lltype.Array(lltype.Ptr(S1), hints={'nolength': True})
  616. S2 = lltype.Struct('S2', ('a', lltype.Ptr(A2)))
  617. S2Forward.become(S2)
  618. s1 = lltype.malloc(S1, flavor='raw')
  619. a2 = lltype.malloc(A2, 10, flavor='raw')
  620. s2 = lltype.malloc(S2, flavor='raw')
  621. s2.a = a2
  622. a2[5] = s1
  623. s1.p = s2
  624. ac2 = lltype2ctypes(a2, normalize=False)
  625. sc1 = ac2.contents.items[5]
  626. sc2 = sc1.contents.p
  627. assert (ctypes.addressof(sc2.contents.a.contents) ==
  628. ctypes.addressof(ac2.contents))
  629. lltype.free(s1, flavor='raw')
  630. lltype.free(a2, flavor='raw')
  631. lltype.free(s2, flavor='raw')
  632. assert not ALLOCATED # detects memory leaks in the test
  633. def test_arrayofstruct(self):
  634. S1 = lltype.Struct('S2', ('x', lltype.Signed))
  635. A = lltype.Array(S1, hints={'nolength': True})
  636. a = lltype.malloc(A, 5, flavor='raw')
  637. a[0].x = 100
  638. a[1].x = 101
  639. a[2].x = 102
  640. a[3].x = 103
  641. a[4].x = 104
  642. ac = lltype2ctypes(a, normalize=False)
  643. assert ac.contents.items[0].x == 100
  644. assert ac.contents.items[2].x == 102
  645. ac.contents.items[3].x += 500
  646. assert a[3].x == 603
  647. a[4].x += 600
  648. assert ac.contents.items[4].x == 704
  649. a1 = ctypes2lltype(lltype.Ptr(A), ac)
  650. assert a1 == a
  651. assert a1[2].x == 102
  652. aitem1 = ctypes2lltype(lltype.Ptr(S1),
  653. ctypes.pointer(ac.contents.items[1]))
  654. assert aitem1.x == 101
  655. assert aitem1 == a1[1]
  656. lltype.free(a, flavor='raw')
  657. assert not ALLOCATED # detects memory leaks in the test
  658. def test_get_errno(self):
  659. eci = ExternalCompilationInfo(includes=['string.h'])
  660. if sys.platform.startswith('win'):
  661. underscore_on_windows = '_'
  662. else:
  663. underscore_on_windows = ''
  664. strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T,
  665. compilation_info=eci)
  666. os_write = rffi.llexternal(underscore_on_windows+'write',
  667. [rffi.INT, rffi.CCHARP, rffi.SIZE_T],
  668. rffi.SIZE_T)
  669. buffer = lltype.malloc(rffi.CCHARP.TO, 5, flavor='raw')
  670. written = os_write(12312312, buffer, 5)
  671. lltype.free(buffer, flavor='raw')
  672. assert rffi.cast(lltype.Signed, written) < 0
  673. # the next line is a random external function call,
  674. # to check that it doesn't reset errno
  675. strlen("hi!")
  676. err = rposix.get_errno()
  677. import errno
  678. assert err == errno.EBADF
  679. assert not ALLOCATED # detects memory leaks in the test
  680. def test_call_with_struct_argument(self):
  681. # XXX is there such a function in the standard C headers?
  682. from pypy.rlib import _rsocket_rffi
  683. buf = rffi.make(_rsocket_rffi.in_addr)
  684. rffi.cast(rffi.CCHARP, buf)[0] = '\x01'
  685. rffi.cast(rffi.CCHARP, buf)[1] = '\x02'
  686. rffi.cast(rffi.CCHARP, buf)[2] = '\x03'
  687. rffi.cast(rffi.CCHARP, buf)[3] = '\x04'
  688. p = _rsocket_rffi.inet_ntoa(buf)
  689. assert rffi.charp2str(p) == '1.2.3.4'
  690. lltype.free(buf, flavor='raw')
  691. assert not ALLOCATED # detects memory leaks in the test
  692. def test_storage_stays_around(self):
  693. data = "hello, world!" * 100
  694. A = lltype.Array(rffi.CHAR, hints={'nolength': True})
  695. S = lltype.Struct('S', ('a', lltype.Ptr(A)))
  696. s = lltype.malloc(S, flavor='raw')
  697. lltype2ctypes(s) # force it to escape
  698. s.a = lltype.malloc(A, len(data), flavor='raw')
  699. # the storage for the array should not be freed by lltype even
  700. # though the _ptr object appears to go away here
  701. for i in xrange(len(data)):
  702. s.a[i] = data[i]
  703. for i in xrange(len(data)):
  704. assert s.a[i] == data[i]
  705. lltype.free(s.a, flavor='raw')
  706. lltype.free(s, flavor='raw')
  707. assert not ALLOCATED # detects memory leaks in the test
  708. def test_arrayoffloat(self):
  709. a = lltype.malloc(rffi.FLOATP.TO, 3, flavor='raw')
  710. a[0] = rffi.r_singlefloat(0.0)
  711. a[1] = rffi.r_singlefloat(1.1)
  712. a[2] = rffi.r_singlefloat(2.2)
  713. ac = lltype2ctypes(a, normalize=False)
  714. assert ac.contents.items[0] == 0.0
  715. assert abs(ac.contents.items[1] - 1.1) < 1E-6
  716. assert abs(ac.contents.items[2] - 2.2) < 1E-6
  717. b = ctypes2lltype(rffi.FLOATP, ac)
  718. assert isinstance(b[0], rffi.r_singlefloat)
  719. assert float(b[0]) == 0.0
  720. assert isinstance(b[1], rffi.r_singlefloat)
  721. assert abs(float(b[1]) - 1.1) < 1E-6
  722. assert isinstance(b[2], rffi.r_singlefloat)
  723. assert abs(float(b[2]) - 2.2) < 1E-6
  724. lltype.free(a, flavor='raw')
  725. def test_different_signatures(self):
  726. if sys.platform=='win32':
  727. py.test.skip("No fcntl on win32")
  728. fcntl_int = rffi.llexternal('fcntl', [rffi.INT, rffi.INT, rffi.INT],
  729. rffi.INT)
  730. fcntl_str = rffi.llexternal('fcntl', [rffi.INT, rffi.INT, rffi.CCHARP],
  731. rffi.INT)
  732. fcntl_int(12345, 1, 0)
  733. fcntl_str(12345, 3, "xxx")
  734. fcntl_int(12345, 1, 0)
  735. def test_llexternal_source(self):
  736. eci = ExternalCompilationInfo(
  737. separate_module_sources = ["int fn() { return 42; }"],
  738. export_symbols = ['fn'],
  739. )
  740. fn = rffi.llexternal('fn', [], rffi.INT, compilation_info=eci)
  741. res = fn()
  742. assert res == 42
  743. def test_llexternal_macro(self):
  744. eci = ExternalCompilationInfo(
  745. post_include_bits = ["#define fn(x) (42 + x)"],
  746. )
  747. fn1 = rffi.llexternal('fn', [rffi.INT], rffi.INT,
  748. compilation_info=eci, macro=True)
  749. fn2 = rffi.llexternal('fn2', [rffi.DOUBLE], rffi.DOUBLE,
  750. compilation_info=eci, macro='fn')
  751. res = fn1(10)
  752. assert res == 52
  753. res = fn2(10.5)
  754. assert res == 52.5
  755. def test_prebuilt_constant(self):
  756. header = py.code.Source("""
  757. #ifndef _SOME_H
  758. #define _SOME_H
  759. #include <stdlib.h>
  760. static long x = 3;
  761. static int y = 5;
  762. char **z = NULL;
  763. #endif /* _SOME_H */
  764. """)
  765. h_file = udir.join("some_h.h")
  766. h_file.write(header)
  767. eci = ExternalCompilationInfo(includes=['stdio.h', str(h_file.basename)],
  768. include_dirs=[str(udir)])
  769. get_x, set_x = rffi.CExternVariable(rffi.LONG, 'x', eci, c_type='long')
  770. get_y, set_y = rffi.CExternVariable(rffi.INT, 'y', eci, c_type='int')
  771. get_z, set_z = rffi.CExternVariable(rffi.CCHARPP, 'z', eci)
  772. def f():
  773. one = get_x()
  774. set_x(13)
  775. return one + get_x()
  776. def fy():
  777. one = rffi.cast(lltype.Signed, get_y())
  778. set_y(rffi.cast(rffi.INT, 13))
  779. return one + rffi.cast(lltype.Signed, get_y())
  780. def g():
  781. l = rffi.liststr2charpp(["a", "b", "c"])
  782. try:
  783. set_z(l)
  784. return rffi.charp2str(get_z()[2])
  785. finally:
  786. rffi.free_charpp(l)
  787. res = f()
  788. assert res == 16
  789. res = fy()
  790. assert res == 18
  791. res = g()
  792. assert res == "c"
  793. def test_c_callback(self):
  794. c_source = py.code.Source("""
  795. int eating_callback(int arg, int(*call)(int))
  796. {
  797. return call(arg);
  798. }
  799. """)
  800. eci = ExternalCompilationInfo(separate_module_sources=[c_source],
  801. export_symbols=['eating_callback'])
  802. args = [rffi.INT, rffi.CCallback([rffi.INT], rffi.INT)]
  803. eating_callback = rffi.llexternal('eating_callback', args, rffi.INT,
  804. compilation_info=eci)
  805. def g(i):
  806. return i + 3
  807. def f():
  808. return eating_callback(3, g)
  809. assert f() == 6
  810. def test_qsort_callback(self):
  811. TP = rffi.CArrayPtr(rffi.INT)
  812. a = lltype.malloc(TP.TO, 5, flavor='raw')
  813. a[0] = rffi.r_int(5)
  814. a[1] = rffi.r_int(3)
  815. a[2] = rffi.r_int(2)
  816. a[3] = rffi.r_int(1)
  817. a[4] = rffi.r_int(4)
  818. def compare(a, b):
  819. if a[0] > b[0]:
  820. return rffi.r_int(1)
  821. else:
  822. return rffi.r_int(-1)
  823. CALLBACK = rffi.CCallback([rffi.VOIDP, rffi.VOIDP], rffi.INT)
  824. qsort = rffi.llexternal('qsort', [rffi.VOIDP, rffi.SIZE_T,
  825. rffi.SIZE_T, CALLBACK], lltype.Void)
  826. qsort(rffi.cast(rffi.VOIDP, a), 5, rffi.sizeof(rffi.INT), compare)
  827. for i in range(5):
  828. assert a[i] == i + 1
  829. lltype.free(a, flavor='raw')
  830. def test_array_type_bug(self):
  831. A = lltype.Array(lltype.Signed)
  832. a1 = lltype.malloc(A, 0, flavor='raw')
  833. a2 = lltype.malloc(A, 0, flavor='raw')
  834. c1 = lltype2ctypes(a1)
  835. c2 = lltype2ctypes(a2)
  836. assert type(c1) is type(c2)
  837. lltype.free(a1, flavor='raw')
  838. lltype.free(a2, flavor='raw')
  839. assert not ALLOCATED # detects memory leaks in the test
  840. def test_varsized_struct(self):
  841. S = lltype.Struct('S', ('x', lltype.Signed),
  842. ('a', lltype.Array(lltype.Char)))
  843. s1 = lltype.malloc(S, 6, flavor='raw')
  844. s1.x = 5
  845. s1.a[2] = 'F'
  846. sc = lltype2ctypes(s1, normalize=False)
  847. assert isinstance(sc.contents, ctypes.Structure)
  848. assert sc.contents.x == 5
  849. assert sc.contents.a.length == 6
  850. assert sc.contents.a.items[2] == ord('F')
  851. sc.contents.a.items[3] = ord('P')
  852. assert s1.a[3] == 'P'
  853. s1.a[1] = 'y'
  854. assert sc.contents.a.items[1] == ord('y')
  855. # now go back to lltype...
  856. res = ctypes2lltype(lltype.Ptr(S), sc)
  857. assert res == s1
  858. assert res.x == 5
  859. assert len(res.a) == 6
  860. lltype.free(s1, flavor='raw')
  861. assert not ALLOCATED # detects memory leaks in the test
  862. def test_with_explicit_length(self):
  863. A = lltype.Array(lltype.Signed)
  864. a1 = lltype.malloc(A, 5, flavor='raw')
  865. a1[0] = 42
  866. c1 = lltype2ctypes(a1, normalize=False)
  867. assert c1.contents.length == 5
  868. assert c1.contents.items[0] == 42
  869. res = ctypes2lltype(lltype.Ptr(A), c1)
  870. assert res == a1
  871. assert len(res) == 5
  872. assert res[0] == 42
  873. res[0] += 1
  874. assert c1.contents.items[0] == 43
  875. assert a1[0] == 43
  876. a1[0] += 2
  877. assert c1.contents.items[0] == 45
  878. assert a1[0] == 45
  879. c1.contents.items[0] += 3
  880. assert res[0] == 48
  881. assert a1[0] == 48
  882. lltype.free(a1, flavor='raw')
  883. assert not ALLOCATED # detects memory leaks in the test
  884. def test_c_callback_with_void_arg_2(self):
  885. ftest = []
  886. def f(x):
  887. ftest.append(x)
  888. F = lltype.FuncType([lltype.Void], lltype.Void)
  889. fn = lltype.functionptr(F, 'askjh', _callable=f, _void0=-5)
  890. fn(-5)
  891. assert ftest == [-5]
  892. fn2 = lltype2ctypes(fn)
  893. fn2()
  894. assert ftest == [-5, -5]
  895. fn3 = ctypes2lltype(lltype.Ptr(F), fn2)
  896. fn3(-5)
  897. assert ftest == [-5, -5, -5]
  898. def test_c_callback_with_void_arg_3(self):
  899. import pypy
  900. def f(i):
  901. x = 'X' * i
  902. return x[-2]
  903. a = RPythonAnnotator()
  904. r = a.build_types(f, [int])
  905. rtyper = RPythonTyper(a)
  906. rtyper.specialize()
  907. a.translator.rtyper = rtyper
  908. graph = a.translator.graphs[0]
  909. op = graph.startblock.operations[-1]
  910. assert op.opname == 'direct_call'
  911. assert op.args[0].value._obj._callable == pypy.rpython.lltypesystem.rstr.LLHelpers.ll_stritem.im_func
  912. assert op.args[1].value == pypy.rpython.lltypesystem.rstr.LLHelpers
  913. assert op.args[3].value == -2
  914. def test_recursive_struct_more(self):
  915. NODE = lltype.ForwardReference()
  916. NODE.become(lltype.Struct('NODE', ('value', lltype.Signed),
  917. ('next', lltype.Ptr(NODE))))
  918. CNODEPTR = get_ctypes_type(NODE)
  919. pc = CNODEPTR()
  920. pc.value = 42
  921. pc.next = ctypes.pointer(pc)
  922. p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc))
  923. assert p.value == 42
  924. assert p.next == p
  925. pc2 = lltype2ctypes(p)
  926. assert pc2.contents.value == 42
  927. assert pc2.contents.next.contents.value == 42
  928. def test_indirect_recursive_struct_more(self):
  929. NODE = lltype.ForwardReference()
  930. NODE2 = lltype.Struct('NODE2', ('ping', lltype.Ptr(NODE)))
  931. NODE.become(lltype.Struct('NODE', ('pong', NODE2)))
  932. # Building NODE2 first used to fail.
  933. get_ctypes_type(NODE2)
  934. CNODEPTR = get_ctypes_type(NODE)
  935. pc = CNODEPTR()
  936. pc.pong.ping = ctypes.pointer(pc)
  937. p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc))
  938. assert p.pong.ping == p
  939. def test_typedef(self):
  940. assert ctypes2lltype(lltype.Typedef(lltype.Signed, 'test'), 6) == 6
  941. assert ctypes2lltype(lltype.Typedef(lltype.Float, 'test2'), 3.4) == 3.4
  942. assert get_ctypes_type(lltype.Signed) == get_ctypes_type(
  943. lltype.Typedef(lltype.Signed, 'test3'))
  944. def test_cast_adr_to_int(self):
  945. class someaddr(object):
  946. def _cast_to_int(self):
  947. return sys.maxint/2 * 3
  948. res = cast_adr_to_int(someaddr())
  949. assert isinstance(res, int)
  950. assert res == -sys.maxint/2 - 3
  951. def test_cast_gcref_back_and_forth(self):
  952. NODE = lltype.GcStruct('NODE')
  953. node = lltype.malloc(NODE)
  954. ref = lltype.cast_opaque_ptr(llmemory.GCREF, node)
  955. back = rffi.cast(llmemory.GCREF, rffi.cast(lltype.Signed, ref))
  956. assert lltype.cast_opaque_ptr(lltype.Ptr(NODE), back) == node
  957. def test_gcref_forth_and_back(self):
  958. cp = ctypes.c_void_p(1234)
  959. v = ctypes2lltype(llmemory.GCREF, cp)
  960. assert lltype2ctypes(v).value == cp.value
  961. v1 = ctypes2lltype(llmemory.GCREF, cp)
  962. assert v == v1
  963. assert v
  964. v2 = ctypes2lltype(llmemory.GCREF, ctypes.c_void_p(1235))
  965. assert v2 != v
  966. def test_gcref_type(self):
  967. NODE = lltype.GcStruct('NODE')
  968. node = lltype.malloc(NODE)
  969. ref = lltype.cast_opaque_ptr(llmemory.GCREF, node)
  970. v = lltype2ctypes(ref)
  971. assert isinstance(v, ctypes.c_void_p)
  972. def test_gcref_null(self):
  973. ref = lltype.nullptr(llmemory.GCREF.TO)
  974. v = lltype2ctypes(ref)
  975. assert isinstance(v, ctypes.c_void_p)
  976. def test_cast_null_gcref(self):
  977. ref = lltype.nullptr(llmemory.GCREF.TO)
  978. value = rffi.cast(lltype.Signed, ref)
  979. assert value == 0
  980. def test_cast_null_fakeaddr(self):
  981. ref = llmemory.NULL
  982. value = rffi.cast(lltype.Signed, ref)
  983. assert value == 0
  984. def test_gcref_truth(self):
  985. p0 = ctypes.c_void_p(0)
  986. ref0 = ctypes2lltype(llmemory.GCREF, p0)
  987. assert not ref0
  988. p1234 = ctypes.c_void_p(1234)
  989. ref1234 = ctypes2lltype(llmemory.GCREF, p1234)
  990. assert p1234
  991. def test_gcref_casts(self):
  992. p0 = ctypes.c_void_p(0)
  993. ref0 = ctypes2lltype(llmemory.GCREF, p0)
  994. assert lltype.cast_ptr_to_int(ref0) == 0
  995. assert llmemory.cast_ptr_to_adr(ref0) == llmemory.NULL
  996. NODE = lltype.GcStruct('NODE')
  997. assert lltype.cast_opaque_ptr(lltype.Ptr(NODE), ref0) == lltype.nullptr(NODE)
  998. node = lltype.malloc(NODE)
  999. ref1 = lltype.cast_opaque_ptr(llmemory.GCREF, node)
  1000. intval = rffi.cast(lltype.Signed, node)
  1001. intval1 = rffi.cast(lltype.Signed, ref1)
  1002. assert intval == intval1
  1003. ref2 = ctypes2lltype(llmemory.GCREF, intval1)
  1004. assert lltype.cast_opaque_ptr(lltype.Ptr(NODE), ref2) == node
  1005. #addr = llmemory.cast_ptr_to_adr(ref1)
  1006. #assert llmemory.cast_adr_to_int(addr) == intval
  1007. #assert lltype.cast_ptr_to_int(ref1) == intval
  1008. x = rffi.cast(llmemory.GCREF, -17)
  1009. assert lltype.cast_ptr_to_int(x) == -17
  1010. def test_ptr_truth(self):
  1011. abc = rffi.cast(lltype.Ptr(lltype.FuncType([], lltype.Void)), 0)
  1012. assert not abc
  1013. def test_mixed_gcref_comparison(self):
  1014. NODE = lltype.GcStruct('NODE')
  1015. node = lltype.malloc(NODE)
  1016. ref1 = lltype.cast_opaque_ptr(llmemory.GCREF, node)
  1017. ref2 = rffi.cast(llmemory.GCREF, 123)
  1018. assert ref1 != ref2
  1019. assert not (ref1 == ref2)
  1020. assert ref2 != ref1
  1021. assert not (ref2 == ref1)
  1022. assert node._obj._storage is True
  1023. # forced!
  1024. rffi.cast(lltype.Signed, ref1)
  1025. assert node._obj._storage not in (True, None)
  1026. assert ref1 != ref2
  1027. assert not (ref1 == ref2)
  1028. assert ref2 != ref1
  1029. assert not (ref2 == ref1)
  1030. def test_gcref_comparisons_back_and_forth(self):
  1031. NODE = lltype.GcStruct('NODE')
  1032. node = lltype.malloc(NODE)
  1033. ref1 = lltype.cast_opaque_ptr(llmemory.GCREF, node)
  1034. numb = rffi.cast(lltype.Signed, ref1)
  1035. ref2 = rffi.cast(llmemory.GCREF, numb)
  1036. assert ref1 == ref2
  1037. assert ref2 == ref1
  1038. assert not (ref1 != ref2)
  1039. assert not (ref2 != ref1)
  1040. def test_convert_subarray(self):
  1041. A = lltype.GcArray(lltype.Signed)
  1042. a = lltype.malloc(A, 20)
  1043. inside = lltype.direct_ptradd(lltype.direct_arrayitems(a), 3)
  1044. lltype2ctypes(inside)
  1045. start = rffi.cast(lltype.Signed, lltype.direct_arrayitems(a))
  1046. inside_int = rffi.cast(lltype.Signed, inside)
  1047. assert inside_int == start+rffi.sizeof(lltype.Signed)*3
  1048. def test_gcref_comparisons_through_addresses(self):
  1049. NODE = lltype.GcStruct('NODE')
  1050. n0 = lltype.malloc(NODE)
  1051. adr0 = llmemory.cast_ptr_to_adr(n0)
  1052. n1 = lltype.malloc(NODE)
  1053. i1 = rffi.cast(lltype.Signed, n1)
  1054. ref1 = rffi.cast(llmemory.GCREF, i1)
  1055. adr1 = llmemory.cast_ptr_to_adr(ref1)
  1056. assert adr1 != adr0
  1057. assert adr0 != adr1
  1058. adr1_2 = llmemory.cast_ptr_to_adr(n1)
  1059. #import pdb; pdb.set_trace()
  1060. assert adr1_2 == adr1
  1061. assert adr1 == adr1_2
  1062. def test_object_subclass(self):
  1063. from pypy.rpython.lltypesystem import rclass
  1064. from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
  1065. from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
  1066. class S:
  1067. pass
  1068. def f(n):
  1069. s = S()
  1070. s.x = n
  1071. ls = cast_instance_to_base_ptr(s)
  1072. as_num = rffi.cast(lltype.Signed, ls)
  1073. # --- around this point, only 'as_num' is passed
  1074. t = rffi.cast(rclass.OBJECTPTR, as_num)
  1075. u = cast_base_ptr_to_instance(S, t)
  1076. return u.x
  1077. res = interpret(f, [123])
  1078. assert res == 123
  1079. def test_object_subclass_2(self):
  1080. from pypy.rpython.lltypesystem import rclass
  1081. SCLASS = lltype.GcStruct('SCLASS',
  1082. ('parent', rclass.OBJECT),
  1083. ('n', lltype.Signed))
  1084. sclass_vtable = lltype.malloc(rclass.OBJECT_VTABLE, zero=True,
  1085. immortal=True)
  1086. sclass_vtable.name = rclass.alloc_array_name('SClass')
  1087. def f(n):
  1088. rclass.declare_type_for_typeptr(sclass_vtable, SCLASS)
  1089. s = lltype.malloc(SCLASS)
  1090. s.parent.typeptr = sclass_vtable
  1091. s.n = n
  1092. as_num = rffi.cast(lltype.Signed, s)
  1093. # --- around this point, only 'as_num' is passed
  1094. t = rffi.cast(lltype.Ptr(SCLASS), as_num)
  1095. return t.n
  1096. res = interpret(f, [123])
  1097. assert res == 123
  1098. def test_object_subclass_3(self):
  1099. from pypy.rpython.lltypesystem import rclass
  1100. from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
  1101. from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
  1102. class S:
  1103. pass
  1104. def f(n):
  1105. s = S()
  1106. s.x = n
  1107. ls = cast_instance_to_base_ptr(s)
  1108. as_num = rffi.cast(lltype.Signed, ls)
  1109. # --- around this point, only 'as_num' is passed
  1110. r = rffi.cast(llmemory.GCREF, as_num)
  1111. t = lltype.cast_opaque_ptr(rclass.OBJECTPTR, r)
  1112. u = cast_base_ptr_to_instance(S, t)
  1113. return u.x
  1114. res = interpret(f, [123])
  1115. assert res == 123
  1116. def test_object_subclass_4(self):
  1117. from pypy.rpython.lltypesystem import rclass
  1118. SCLASS = lltype.GcStruct('SCLASS',
  1119. ('parent', rclass.OBJECT),
  1120. ('n', lltype.Signed))
  1121. sclass_vtable = lltype.malloc(rclass.OBJECT_VTABLE, zero=True,
  1122. immortal=True)
  1123. sclass_vtable.name = rclass.alloc_array_name('SClass')
  1124. def f(n):
  1125. rclass.declare_type_for_typeptr(sclass_vtable, SCLASS)
  1126. s = lltype.malloc(SCLASS)
  1127. s.parent.typeptr = sclass_vtable
  1128. s.n = n
  1129. as_num = rffi.cast(lltype.Signed, s)
  1130. # --- around this point, only 'as_num' is passed
  1131. r = rffi.cast(llmemory.GCREF, as_num)
  1132. t = lltype.cast_opaque_ptr(lltype.Ptr(SCLASS), r)
  1133. return t.n
  1134. res = interpret(f, [123])
  1135. assert res == 123
  1136. def test_object_subclass_5(self):
  1137. from pypy.rpython.lltypesystem import rclass
  1138. from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
  1139. from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
  1140. class S:
  1141. x = 5 # entry in the vtable
  1142. class T(S):
  1143. x = 6
  1144. def f():
  1145. s = T()
  1146. ls = cast_instance_to_base_ptr(s)
  1147. as_num = rffi.cast(lltype.Signed, ls)
  1148. # --- around this point, only 'as_num' is passed
  1149. t = rffi.cast(rclass.OBJECTPTR, as_num)
  1150. u = cast_base_ptr_to_instance(S, t)
  1151. return u.x
  1152. res = interpret(f, [])
  1153. assert res == 6
  1154. def test_force_to_int(self):
  1155. S = lltype.Struct('S')
  1156. p = lltype.malloc(S, flavor='raw')
  1157. a = llmemory.cast_ptr_to_adr(p)
  1158. i = llmemory.cast_adr_to_int(a, "forced")
  1159. assert type(i) is int
  1160. assert i == llmemory.cast_adr_to_int(a, "forced")
  1161. lltype.free(p, flavor='raw')
  1162. def test_freelist(self):
  1163. S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
  1164. SP = lltype.Ptr(S)
  1165. chunk = lltype.malloc(rffi.CArrayPtr(S).TO, 10, flavor='raw')
  1166. assert lltype.typeOf(chunk) == rffi.CArrayPtr(S)
  1167. free_list = lltype.nullptr(rffi.VOIDP.TO)
  1168. # build list
  1169. current = chunk
  1170. for i in range(10):
  1171. rffi.cast(rffi.VOIDPP, current)[0] = free_list
  1172. free_list = rffi.cast(rffi.VOIDP, current)
  1173. current = rffi.ptradd(current, 1)
  1174. # get one
  1175. p = free_list
  1176. free_list = rffi.cast(rffi.VOIDPP, p)[0]
  1177. rffi.cast(SP, p).x = 0
  1178. # get two
  1179. p = free_list
  1180. free_list = rffi.cast(rffi.VOIDPP, p)[0]
  1181. rffi.cast(SP, p).x = 0
  1182. # get three
  1183. p = free_list
  1184. free_list = rffi.cast(rffi.VOIDPP, p)[0]
  1185. rffi.cast(SP, p).x = 0
  1186. lltype.free(chunk, flavor='raw')
  1187. def test_opaque_tagged_pointers(self):
  1188. from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
  1189. from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
  1190. from pypy.rpython.lltypesystem import rclass
  1191. class Opaque(object):
  1192. llopaque = True
  1193. def hide(self):
  1194. ptr = cast_instance_to_base_ptr(self)
  1195. return lltype.cast_opaque_ptr(llmemory.GCREF, ptr)
  1196. @staticmethod
  1197. def show(gcref):
  1198. ptr = lltype.cast_opaque_p

Large files files are truncated, but you can click here to view the full file