PageRenderTime 40ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/rpython/lltypesystem/test/test_rffi.py

https://bitbucket.org/pypy/pypy/
Python | 813 lines | 811 code | 2 blank | 0 comment | 0 complexity | 33d2d34dae608feb13f19062da193c2b MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. import sys
  3. from pypy.rpython.lltypesystem.rffi import *
  4. from pypy.rpython.lltypesystem.rffi import _keeper_for_type # crap
  5. from pypy.rlib.rposix import get_errno, set_errno
  6. from pypy.translator.c.test.test_genc import compile as compile_c
  7. from pypy.rpython.lltypesystem.lltype import Signed, Ptr, Char, malloc
  8. from pypy.rpython.lltypesystem.rstr import STR
  9. from pypy.rpython.lltypesystem import lltype
  10. from pypy.tool.udir import udir
  11. from pypy.rpython.test.test_llinterp import interpret
  12. from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
  13. from pypy.annotation.annrpython import RPythonAnnotator
  14. from pypy.rpython.rtyper import RPythonTyper
  15. from pypy.translator.backendopt.all import backend_optimizations
  16. from pypy.translator.translator import graphof
  17. from pypy.conftest import option
  18. from pypy.objspace.flow.model import summary
  19. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  20. from pypy.rlib.rarithmetic import r_singlefloat
  21. class BaseTestRffi:
  22. def test_basic(self):
  23. c_source = py.code.Source("""
  24. int someexternalfunction(int x)
  25. {
  26. return (x + 3);
  27. }
  28. """)
  29. eci = ExternalCompilationInfo(separate_module_sources=[c_source])
  30. z = llexternal('someexternalfunction', [Signed], Signed,
  31. compilation_info=eci)
  32. def f():
  33. return z(8)
  34. xf = self.compile(f, [])
  35. assert xf() == 8+3
  36. def test_hashdefine(self):
  37. h_source = """
  38. #define X(i) (i+3)
  39. """
  40. h_file = udir.join("stuff.h")
  41. h_file.write(h_source)
  42. eci = ExternalCompilationInfo(includes=['stuff.h'],
  43. include_dirs=[udir])
  44. z = llexternal('X', [Signed], Signed, compilation_info=eci)
  45. def f():
  46. return z(8)
  47. xf = self.compile(f, [])
  48. assert xf() == 8+3
  49. def test_string(self):
  50. eci = ExternalCompilationInfo(includes=['string.h'])
  51. z = llexternal('strlen', [CCHARP], Signed, compilation_info=eci)
  52. def f():
  53. s = str2charp("xxx")
  54. res = z(s)
  55. free_charp(s)
  56. return res
  57. xf = self.compile(f, [], backendopt=False)
  58. assert xf() == 3
  59. def test_unicode(self):
  60. eci = ExternalCompilationInfo(includes=['string.h'])
  61. z = llexternal('wcslen', [CWCHARP], Signed, compilation_info=eci)
  62. def f():
  63. s = unicode2wcharp(u"xxx\xe9")
  64. res = z(s)
  65. free_wcharp(s)
  66. return res
  67. xf = self.compile(f, [], backendopt=False)
  68. assert xf() == 4
  69. def test_string_reverse(self):
  70. c_source = py.code.Source("""
  71. #include <string.h>
  72. #include <src/allocator.h>
  73. #include <src/mem.h>
  74. char *f(char* arg)
  75. {
  76. char *ret;
  77. /* lltype.free uses OP_RAW_FREE, we must allocate
  78. * with the matching function
  79. */
  80. OP_RAW_MALLOC(strlen(arg) + 1, ret, char*)
  81. strcpy(ret, arg);
  82. return ret;
  83. }
  84. """)
  85. eci = ExternalCompilationInfo(separate_module_sources=[c_source],
  86. post_include_bits=['char *f(char*);'])
  87. z = llexternal('f', [CCHARP], CCHARP, compilation_info=eci)
  88. def f():
  89. s = str2charp("xxx")
  90. l_res = z(s)
  91. res = charp2str(l_res)
  92. lltype.free(l_res, flavor='raw')
  93. free_charp(s)
  94. return len(res)
  95. xf = self.compile(f, [], backendopt=False)
  96. assert xf(expected_extra_mallocs=-1) == 3
  97. def test_stringstar(self):
  98. c_source = """
  99. #include <string.h>
  100. int f(char *args[]) {
  101. char **p = args;
  102. int l = 0;
  103. while (*p) {
  104. l += strlen(*p);
  105. p++;
  106. }
  107. return (l);
  108. }
  109. """
  110. eci = ExternalCompilationInfo(separate_module_sources=[c_source])
  111. z = llexternal('f', [CCHARPP], Signed, compilation_info=eci)
  112. def f():
  113. l = ["xxx", "x", "xxxx"]
  114. ss = liststr2charpp(l)
  115. result = z(ss)
  116. free_charpp(ss)
  117. return result
  118. xf = self.compile(f, [], backendopt=False)
  119. assert xf() == 8
  120. def test_struct(self):
  121. h_source = """
  122. #ifndef _MY_SOURCE_H
  123. #define _MY_SOURCE_H
  124. struct xx {
  125. int one;
  126. char two;
  127. int three;
  128. };
  129. #endif
  130. """
  131. h_file = udir.join("structxx.h")
  132. h_file.write(h_source)
  133. c_source = """
  134. #include <structxx.h>
  135. int f(struct xx* z)
  136. {
  137. return (z->one + z->three);
  138. }
  139. """
  140. TP = CStructPtr('xx', ('one', INT), ('two', Char), ('three', INT))
  141. eci = ExternalCompilationInfo(
  142. includes=['structxx.h'],
  143. include_dirs=[udir],
  144. separate_module_sources=[c_source]
  145. )
  146. z = llexternal('f', [TP], INT, compilation_info=eci)
  147. def f():
  148. struct = lltype.malloc(TP.TO, flavor='raw')
  149. struct.c_one = cast(INT, 3)
  150. struct.c_two = '\x33'
  151. struct.c_three = cast(INT, 5)
  152. result = z(struct)
  153. lltype.free(struct, flavor='raw')
  154. return cast(LONG, result)
  155. fn = self.compile(f, [], backendopt=False)
  156. assert fn() == 8
  157. def test_externvar(self):
  158. import os
  159. if os.name == 'nt':
  160. # Windows CRT badly aborts when an invalid fd is used.
  161. bad_fd = 0
  162. else:
  163. bad_fd = 12312312
  164. def f():
  165. set_errno(12)
  166. return get_errno()
  167. def g():
  168. try:
  169. os.write(bad_fd, "xxx")
  170. except OSError:
  171. pass
  172. return get_errno()
  173. fn = self.compile(f, [])
  174. assert fn() == 12
  175. gn = self.compile(g, [])
  176. import errno
  177. assert gn() == errno.EBADF
  178. def test_extra_include_dirs(self):
  179. udir.ensure("incl", dir=True)
  180. udir.join("incl", "incl.h").write("#define C 3")
  181. c_source = py.code.Source("""
  182. #include <incl.h>
  183. int fun ()
  184. {
  185. return (C);
  186. }
  187. """)
  188. eci = ExternalCompilationInfo(
  189. includes=['incl.h'],
  190. include_dirs=[str(udir.join('incl'))],
  191. separate_module_sources=[c_source]
  192. )
  193. z = llexternal('fun', [], Signed, compilation_info=eci)
  194. def f():
  195. return z()
  196. res = self.compile(f, [])
  197. assert res() == 3
  198. def test_compile_cast(self):
  199. def f(n):
  200. return cast(SIZE_T, n)
  201. f1 = self.compile(f, [int])
  202. res = f1(-1)
  203. assert res == r_size_t(-1)
  204. def test_opaque_type(self):
  205. h_source = py.code.Source("""
  206. #ifndef _OPAQUE_H
  207. #define _OPAQUE_H
  208. struct stuff {
  209. char data[38];
  210. };
  211. #endif /* _OPAQUE_H */
  212. """)
  213. c_source = py.code.Source("""
  214. #include "opaque.h"
  215. char get(struct stuff* x)
  216. {
  217. x->data[13] = 'a';
  218. return x->data[13];
  219. }
  220. """)
  221. # if it doesn't segfault, than we probably malloced it :-)
  222. h_file = udir.join("opaque.h")
  223. h_file.write(h_source)
  224. from pypy.rpython.tool import rffi_platform
  225. eci = ExternalCompilationInfo(
  226. includes=['opaque.h'],
  227. include_dirs=[str(udir)],
  228. separate_module_sources=[c_source]
  229. )
  230. STUFFP = COpaquePtr('struct stuff', compilation_info=eci)
  231. ll_get = llexternal('get', [STUFFP], CHAR, compilation_info=eci)
  232. def f():
  233. ll_stuff = lltype.malloc(STUFFP.TO, flavor='raw')
  234. result = ll_get(ll_stuff)
  235. lltype.free(ll_stuff, flavor='raw')
  236. return result
  237. f1 = self.compile(f, [])
  238. assert f1() == 'a'
  239. def test_opaque_typedef(self):
  240. code = """
  241. #include <stddef.h>
  242. struct stuff;
  243. typedef struct stuff *stuff_ptr;
  244. static int get(stuff_ptr ptr) { return (ptr != NULL); }
  245. """
  246. eci = ExternalCompilationInfo(
  247. post_include_bits = [code]
  248. )
  249. STUFFP = COpaquePtr(typedef='stuff_ptr', compilation_info=eci)
  250. ll_get = llexternal('get', [STUFFP], lltype.Signed,
  251. compilation_info=eci)
  252. def f():
  253. return ll_get(lltype.nullptr(STUFFP.TO))
  254. f1 = self.compile(f, [])
  255. assert f1() == 0
  256. def return_char(self, signed):
  257. ctype_pref = ["un", ""][signed]
  258. rffi_type = [UCHAR, SIGNEDCHAR][signed]
  259. h_source = py.code.Source("""
  260. %ssigned char returnchar(void)
  261. {
  262. return 42;
  263. }
  264. """ % (ctype_pref, ))
  265. h_file = udir.join("opaque2%s.h" % (ctype_pref, ))
  266. h_file.write(h_source)
  267. from pypy.rpython.tool import rffi_platform
  268. eci = ExternalCompilationInfo(
  269. includes=[h_file.basename],
  270. include_dirs=[str(udir)]
  271. )
  272. ll_returnchar = llexternal('returnchar', [], rffi_type, compilation_info=eci)
  273. def f():
  274. result = ll_returnchar()
  275. return result
  276. f1 = self.compile(f, [])
  277. assert f1() == chr(42)
  278. def test_generate_return_char_tests(self):
  279. yield self.return_char, False
  280. yield self.return_char, True
  281. def test_prebuilt_constant(self):
  282. py.test.skip("Think how to do it sane")
  283. h_source = py.code.Source("""
  284. int x = 3;
  285. char** z = NULL;
  286. #endif
  287. """)
  288. h_include = udir.join('constants.h')
  289. h_include.write(h_source)
  290. eci = ExternalCompilationInfo(includes=['stdio.h',
  291. str(h_include.basename)],
  292. include_dirs=[str(udir)])
  293. get_x, set_x = CExternVariable(lltype.Signed, 'x', eci)
  294. get_z, set_z = CExternVariable(CCHARPP, 'z', eci)
  295. def f():
  296. one = get_x()
  297. set_x(13)
  298. return one + get_x()
  299. def g():
  300. l = liststr2charpp(["a", "b", "c"])
  301. try:
  302. set_z(l)
  303. return charp2str(get_z()[2])
  304. finally:
  305. free_charpp(l)
  306. fn = self.compile(f, [])
  307. assert fn() == 16
  308. gn = self.compile(g, [])
  309. assert gn() == "c"
  310. def eating_callback(self):
  311. h_source = py.code.Source("""
  312. #ifndef _CALLBACK_H
  313. #define _CALLBACK_H
  314. extern long eating_callback(long arg, long(*call)(long));
  315. #endif /* _CALLBACK_H */
  316. """)
  317. h_include = udir.join('callback.h')
  318. h_include.write(h_source)
  319. c_source = py.code.Source("""
  320. long eating_callback(long arg, long(*call)(long))
  321. {
  322. long res = call(arg);
  323. if (res == -1)
  324. return -1;
  325. return res;
  326. }
  327. """)
  328. eci = ExternalCompilationInfo(includes=['callback.h'],
  329. include_dirs=[str(udir)],
  330. separate_module_sources=[c_source],
  331. export_symbols=['eating_callback'])
  332. args = [LONG, CCallback([LONG], LONG)]
  333. eating_callback = llexternal('eating_callback', args, LONG,
  334. compilation_info=eci)
  335. return eating_callback
  336. def test_c_callback(self):
  337. eating_callback = self.eating_callback()
  338. def g(i):
  339. return i + 3
  340. def f():
  341. return eating_callback(3, g)
  342. fn = self.compile(f, [])
  343. assert fn() == 6
  344. assert eating_callback._ptr._obj._callbacks.callbacks == {g: True}
  345. def test_double_callback(self):
  346. eating_callback = self.eating_callback()
  347. def one(i):
  348. return i
  349. def two(i):
  350. return i + 2
  351. def f(i):
  352. if i > 3:
  353. return eating_callback(i, one)
  354. else:
  355. return eating_callback(i, two)
  356. fn = self.compile(f, [int])
  357. assert fn(4) == 4
  358. assert fn(1) == 3
  359. assert eating_callback._ptr._obj._callbacks.callbacks == {one: True,
  360. two: True}
  361. def test_exception_callback(self):
  362. eating_callback = self.eating_callback()
  363. def raising(i):
  364. if i > 3:
  365. raise ValueError
  366. else:
  367. return 3
  368. raising._errorcode_ = -1
  369. def f(i):
  370. return eating_callback(i, raising)
  371. fn = self.compile(f, [int])
  372. assert fn(13) == -1
  373. def test_callback_already_llptr(self):
  374. eating_callback = self.eating_callback()
  375. def g(i):
  376. return i + 3
  377. G = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
  378. def f():
  379. return eating_callback(3, llhelper(G, g))
  380. fn = self.compile(f, [])
  381. assert fn() == 6
  382. def test_pass_opaque_pointer_via_callback(self):
  383. eating_callback = self.eating_callback()
  384. TP = lltype.Ptr(lltype.GcStruct('X', ('x', lltype.Signed)))
  385. struct = lltype.malloc(TP.TO) # gc structure
  386. struct.x = 8
  387. def g(i):
  388. return get_keepalive_object(i, TP).x
  389. pos = register_keepalive(struct)
  390. assert _keeper_for_type(TP).stuff_to_keepalive[pos] is struct
  391. del struct
  392. res = eating_callback(pos, g)
  393. unregister_keepalive(pos, TP)
  394. assert res == 8
  395. def test_nonmoving(self):
  396. d = 'non-moving data stuff'
  397. def f():
  398. raw_buf, gc_buf = alloc_buffer(len(d))
  399. try:
  400. for i in range(len(d)):
  401. raw_buf[i] = d[i]
  402. return str_from_buffer(raw_buf, gc_buf, len(d), len(d)-1)
  403. finally:
  404. keep_buffer_alive_until_here(raw_buf, gc_buf)
  405. assert f() == d[:-1]
  406. fn = self.compile(f, [], gcpolicy='ref')
  407. assert fn() == d[:-1]
  408. def test_nonmoving_unicode(self):
  409. d = u'non-moving data'
  410. def f():
  411. raw_buf, gc_buf = alloc_unicodebuffer(len(d))
  412. try:
  413. for i in range(len(d)):
  414. raw_buf[i] = d[i]
  415. return unicode_from_buffer(raw_buf, gc_buf, len(d), len(d)-1)
  416. finally:
  417. keep_unicodebuffer_alive_until_here(raw_buf, gc_buf)
  418. assert f() == d[:-1]
  419. fn = self.compile(f, [], gcpolicy='ref')
  420. assert fn() == d[:-1]
  421. def test_nonmovingbuffer(self):
  422. d = 'some cool data that should not move'
  423. def f():
  424. buf = get_nonmovingbuffer(d)
  425. try:
  426. counter = 0
  427. for i in range(len(d)):
  428. if buf[i] == d[i]:
  429. counter += 1
  430. return counter
  431. finally:
  432. free_nonmovingbuffer(d, buf)
  433. assert f() == len(d)
  434. fn = self.compile(f, [], gcpolicy='ref')
  435. assert fn() == len(d)
  436. def test_nonmovingbuffer_semispace(self):
  437. d = 'cool data'
  438. def f():
  439. counter = 0
  440. for n in range(32):
  441. buf = get_nonmovingbuffer(d)
  442. try:
  443. for i in range(len(d)):
  444. if buf[i] == d[i]:
  445. counter += 1
  446. finally:
  447. free_nonmovingbuffer(d, buf)
  448. return counter
  449. fn = self.compile(f, [], gcpolicy='semispace')
  450. # The semispace gc uses raw_malloc for its internal data structs
  451. # but hopefully less than 30 times. So we should get < 30 leaks
  452. # unless the get_nonmovingbuffer()/free_nonmovingbuffer() pair
  453. # leaks at each iteration. This is what the following line checks.
  454. res = fn(expected_extra_mallocs=range(30))
  455. assert res == 32 * len(d)
  456. class TestRffiInternals:
  457. def test_struct_create(self):
  458. X = CStruct('xx', ('one', INT))
  459. def f():
  460. p = make(X, c_one=cast(INT, 3))
  461. res = p.c_one
  462. lltype.free(p, flavor='raw')
  463. return cast(LONG, res)
  464. assert f() == 3
  465. assert interpret(f, []) == 3
  466. def test_structcopy(self):
  467. X2 = lltype.Struct('X2', ('x', LONG))
  468. X1 = lltype.Struct('X1', ('a', LONG), ('x2', X2), ('p', lltype.Ptr(X2)))
  469. def f():
  470. p2 = make(X2, x=123)
  471. p1 = make(X1, a=5, p=p2)
  472. p1.x2.x = 456
  473. p1bis = make(X1)
  474. p2bis = make(X2)
  475. structcopy(p1bis, p1)
  476. assert p1bis.a == 5
  477. assert p1bis.x2.x == 456
  478. assert p1bis.p == p2
  479. structcopy(p2bis, p2)
  480. res = p2bis.x
  481. lltype.free(p2bis, flavor='raw')
  482. lltype.free(p1bis, flavor='raw')
  483. lltype.free(p2, flavor='raw')
  484. lltype.free(p1, flavor='raw')
  485. return res
  486. assert f() == 123
  487. res = interpret(f, [])
  488. assert res == 123
  489. def test_make_annotation(self):
  490. X = CStruct('xx', ('one', INT))
  491. def f():
  492. p = make(X)
  493. try:
  494. q = make(X)
  495. lltype.free(q, flavor='raw')
  496. finally:
  497. lltype.free(p, flavor='raw')
  498. return 3
  499. assert interpret(f, []) == 3
  500. def test_implicit_cast(self):
  501. z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT,
  502. sandboxsafe=True) # to allow the wrapper to be inlined
  503. def f(x, y, xx, yy):
  504. return z(x, y, xx, yy)
  505. a = RPythonAnnotator()
  506. r = a.build_types(f, [int, int, int, int])
  507. rtyper = RPythonTyper(a)
  508. rtyper.specialize()
  509. a.translator.rtyper = rtyper
  510. backend_optimizations(a.translator)
  511. if option.view:
  512. a.translator.view()
  513. graph = graphof(a.translator, f)
  514. s = summary(graph)
  515. # there should be not too many operations here by now
  516. expected = {'force_cast': 3, 'cast_int_to_float': 1, 'direct_call': 1}
  517. for k, v in expected.items():
  518. assert s[k] == v
  519. def test_stringpolicy1(self):
  520. eci = ExternalCompilationInfo(includes=['string.h'])
  521. strlen = llexternal('strlen', [CCHARP], SIZE_T, compilation_info=eci)
  522. def f():
  523. return cast(LONG, strlen("Xxx"))
  524. assert interpret(f, [], backendopt=True) == 3
  525. def test_stringpolicy3(self):
  526. eci = ExternalCompilationInfo(includes=['string.h'])
  527. strlen = llexternal('strlen', [CCHARP], INT, compilation_info=eci)
  528. def f():
  529. ll_str = str2charp("Xxx")
  530. res = strlen(ll_str)
  531. lltype.free(ll_str, flavor='raw')
  532. return res
  533. assert interpret(f, [], backendopt=True) == 3
  534. def test_stringpolicy_mixed(self):
  535. eci = ExternalCompilationInfo(includes=['string.h'])
  536. strlen = llexternal('strlen', [CCHARP], SIZE_T,
  537. compilation_info=eci)
  538. def f():
  539. res1 = strlen("abcd")
  540. ll_str = str2charp("Xxx")
  541. res2 = strlen(ll_str)
  542. lltype.free(ll_str, flavor='raw')
  543. return cast(LONG, res1*10 + res2)
  544. assert interpret(f, [], backendopt=True) == 43
  545. def test_around_extcall(self):
  546. if sys.platform == "win32":
  547. py.test.skip('No pipes on windows')
  548. import os
  549. from pypy.annotation import model as annmodel
  550. from pypy.rlib.objectmodel import invoke_around_extcall
  551. from pypy.rpython.extfuncregistry import register_external
  552. read_fd, write_fd = os.pipe()
  553. try:
  554. # we need an external function that is not going to get wrapped around
  555. # before()/after() calls, in order to call it from before()/after()...
  556. def mywrite(s):
  557. os.write(write_fd, s)
  558. def llimpl(s):
  559. s = ''.join(s.chars)
  560. os.write(write_fd, s)
  561. register_external(mywrite, [str], annmodel.s_None, 'll_mywrite',
  562. llfakeimpl=llimpl, sandboxsafe=True)
  563. def before():
  564. mywrite("B")
  565. def after():
  566. mywrite("A")
  567. def f():
  568. os.write(write_fd, "-")
  569. invoke_around_extcall(before, after)
  570. os.write(write_fd, "E")
  571. interpret(f, [])
  572. data = os.read(read_fd, 99)
  573. assert data == "-BEA"
  574. finally:
  575. os.close(write_fd)
  576. os.close(read_fd)
  577. def test_external_callable(self):
  578. """ Try to call some llexternal function with llinterp
  579. """
  580. z = llexternal('z', [Signed], Signed, _callable=lambda x:x+1)
  581. def f():
  582. return z(2)
  583. res = interpret(f, [])
  584. assert res == 3
  585. def test_size_t_sign(self):
  586. assert r_size_t(-1) > 0
  587. def test_cast(self):
  588. res = cast(SIZE_T, -1)
  589. assert type(res) is r_size_t
  590. assert res == r_size_t(-1)
  591. #
  592. res = cast(lltype.Signed, 42.5)
  593. assert res == 42
  594. res = cast(lltype.SingleFloat, 12.3)
  595. assert res == r_singlefloat(12.3)
  596. res = cast(lltype.SingleFloat, res)
  597. assert res == r_singlefloat(12.3)
  598. res = cast(lltype.Float, r_singlefloat(12.))
  599. assert res == 12.
  600. def test_rffi_sizeof(self):
  601. try:
  602. import ctypes
  603. except ImportError:
  604. py.test.skip("Cannot test without ctypes")
  605. cache = {
  606. lltype.Signed: ctypes.c_long,
  607. lltype.Unsigned: ctypes.c_ulong,
  608. lltype.UniChar: ctypes.c_wchar,
  609. lltype.Char: ctypes.c_ubyte,
  610. DOUBLE: ctypes.c_double,
  611. FLOAT: ctypes.c_float,
  612. SIGNEDCHAR: ctypes.c_byte,
  613. UCHAR: ctypes.c_ubyte,
  614. SHORT: ctypes.c_short,
  615. USHORT: ctypes.c_ushort,
  616. INT: ctypes.c_int,
  617. UINT: ctypes.c_uint,
  618. LONG: ctypes.c_long,
  619. ULONG: ctypes.c_ulong,
  620. LONGLONG: ctypes.c_longlong,
  621. ULONGLONG: ctypes.c_ulonglong,
  622. SIZE_T: ctypes.c_size_t,
  623. }
  624. for ll, ctp in cache.items():
  625. assert sizeof(ll) == ctypes.sizeof(ctp)
  626. assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll)
  627. assert not size_and_sign(lltype.Signed)[1]
  628. assert size_and_sign(lltype.Char) == (1, True)
  629. assert size_and_sign(lltype.UniChar)[1]
  630. assert size_and_sign(UINT)[1]
  631. assert not size_and_sign(INT)[1]
  632. def test_rffi_offsetof(self):
  633. import struct
  634. from pypy.rpython.tool import rffi_platform
  635. S = rffi_platform.getstruct("struct S",
  636. """
  637. struct S {
  638. short a;
  639. int b, c;
  640. }; """,
  641. [("a", INT),
  642. ("b", INT),
  643. ("c", INT)])
  644. assert sizeof(S) == struct.calcsize("hii")
  645. assert offsetof(S, "c_a") == 0
  646. assert offsetof(S, "c_b") == struct.calcsize("hi") - struct.calcsize("i")
  647. assert offsetof(S, "c_c") == struct.calcsize("hii") - struct.calcsize("i")
  648. ARRAY_OF_CHAR = lltype.Array(CHAR, hints={'nolength': True})
  649. def test_ptradd():
  650. data = "hello, world!"
  651. a = lltype.malloc(ARRAY_OF_CHAR, len(data), flavor='raw')
  652. for i in xrange(len(data)):
  653. a[i] = data[i]
  654. a2 = ptradd(a, 2)
  655. assert lltype.typeOf(a2) == lltype.typeOf(a) == lltype.Ptr(ARRAY_OF_CHAR)
  656. for i in xrange(len(data) - 2):
  657. assert a2[i] == a[i + 2]
  658. lltype.free(a, flavor='raw')
  659. def test_ptradd_interpret():
  660. interpret(test_ptradd, [])
  661. def test_voidptr():
  662. assert repr(VOIDP) == "<* Array of void >"
  663. class TestCRffi(BaseTestRffi):
  664. def compile(self, func, args, **kwds):
  665. return compile_c(func, args, **kwds)
  666. def test_generate_return_char_tests(self):
  667. py.test.skip("GenC does not handle char return values correctly")
  668. def test_enforced_args():
  669. from pypy.annotation.model import s_None
  670. from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
  671. from pypy.translator.interactive import Translation
  672. def f1():
  673. str2charp("hello")
  674. def f2():
  675. str2charp("world")
  676. t = Translation(f1, [])
  677. t.rtype()
  678. mixann = MixLevelHelperAnnotator(t.context.rtyper)
  679. mixann.getgraph(f2, [], s_None)
  680. mixann.finish()
  681. def test_force_cast_unichar():
  682. x = cast(lltype.UniChar, -1)
  683. assert isinstance(x, unicode)
  684. if sys.maxunicode == 65535:
  685. assert cast(LONG, x) == 65535
  686. else:
  687. assert cast(LONG, cast(INT, x)) == -1