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

/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
  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_ptr(lltype.Ptr(rclass.OBJECT), gcref)
  1199. return cast_base_ptr_to_instance(Opaque, ptr)
  1200. opaque = Opaque()
  1201. round = ctypes2lltype(llmemory.GCREF, lltype2ctypes(opaque.hide()))
  1202. assert Opaque.show(round) is opaque
  1203. def test_array_of_structs(self):
  1204. A = lltype.GcArray(lltype.Struct('x', ('v', lltype.Signed)))
  1205. a = lltype.malloc(A, 5)
  1206. a2 = ctypes2lltype(lltype.Ptr(A), lltype2ctypes(a))
  1207. assert a2._obj.getitem(0)._obj._parentstructure() is a2._obj
  1208. class TestPlatform(object):
  1209. def test_lib_on_libpaths(self):
  1210. from pypy.translator.platform import platform
  1211. tmpdir = udir.join('lib_on_libppaths')
  1212. tmpdir.ensure(dir=1)
  1213. c_file = tmpdir.join('c_file.c')
  1214. c_file.write('int f(int a, int b) { return (a + b); }')
  1215. eci = ExternalCompilationInfo(export_symbols=['f'])
  1216. so = platform.compile([c_file], eci, standalone=False)
  1217. eci = ExternalCompilationInfo(
  1218. libraries = ['c_file'],
  1219. library_dirs = [str(so.dirpath())]
  1220. )
  1221. f = rffi.llexternal('f', [rffi.INT, rffi.INT], rffi.INT,
  1222. compilation_info=eci)
  1223. assert f(3, 4) == 7
  1224. def test_prefix(self):
  1225. if not sys.platform.startswith('linux'):
  1226. py.test.skip("Not supported")
  1227. from pypy.translator.platform import platform
  1228. tmpdir = udir.join('lib_on_libppaths_prefix')
  1229. tmpdir.ensure(dir=1)
  1230. c_file = tmpdir.join('c_file.c')
  1231. c_file.write('int f(int a, int b) { return (a + b); }')
  1232. eci = ExternalCompilationInfo()
  1233. so = platform.compile([c_file], eci, standalone=False)
  1234. sopath = py.path.local(so)
  1235. sopath.move(sopath.dirpath().join('libc_file.so'))
  1236. eci = ExternalCompilationInfo(
  1237. libraries = ['c_file'],
  1238. library_dirs = [str(so.dirpath())]
  1239. )
  1240. f = rffi.llexternal('f', [rffi.INT, rffi.INT], rffi.INT,
  1241. compilation_info=eci)
  1242. assert f(3, 4) == 7
  1243. def test_llgcopaque_eq(self):
  1244. assert _llgcopaque(1) != None
  1245. assert _llgcopaque(0) == None