PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/ctypes/test/test_functions.py

https://gitlab.com/unofficial-mirrors/cpython
Python | 402 lines | 285 code | 81 blank | 36 comment | 12 complexity | f6a3e4b78430e7168f972823788a41e6 MD5 | raw file
  1. """
  2. Here is probably the place to write the docs, since the test-cases
  3. show how the type behave.
  4. Later...
  5. """
  6. from ctypes import *
  7. from ctypes.test import need_symbol
  8. import sys, unittest
  9. try:
  10. WINFUNCTYPE
  11. except NameError:
  12. # fake to enable this test on Linux
  13. WINFUNCTYPE = CFUNCTYPE
  14. import _ctypes_test
  15. dll = CDLL(_ctypes_test.__file__)
  16. if sys.platform == "win32":
  17. windll = WinDLL(_ctypes_test.__file__)
  18. class POINT(Structure):
  19. _fields_ = [("x", c_int), ("y", c_int)]
  20. class RECT(Structure):
  21. _fields_ = [("left", c_int), ("top", c_int),
  22. ("right", c_int), ("bottom", c_int)]
  23. class FunctionTestCase(unittest.TestCase):
  24. def test_mro(self):
  25. # in Python 2.3, this raises TypeError: MRO conflict among bases classes,
  26. # in Python 2.2 it works.
  27. #
  28. # But in early versions of _ctypes.c, the result of tp_new
  29. # wasn't checked, and it even crashed Python.
  30. # Found by Greg Chapman.
  31. try:
  32. class X(object, Array):
  33. _length_ = 5
  34. _type_ = "i"
  35. except TypeError:
  36. pass
  37. from _ctypes import _Pointer
  38. try:
  39. class X(object, _Pointer):
  40. pass
  41. except TypeError:
  42. pass
  43. from _ctypes import _SimpleCData
  44. try:
  45. class X(object, _SimpleCData):
  46. _type_ = "i"
  47. except TypeError:
  48. pass
  49. try:
  50. class X(object, Structure):
  51. _fields_ = []
  52. except TypeError:
  53. pass
  54. @need_symbol('c_wchar')
  55. def test_wchar_parm(self):
  56. f = dll._testfunc_i_bhilfd
  57. f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
  58. result = f(1, "x", 3, 4, 5.0, 6.0)
  59. self.assertEqual(result, 139)
  60. self.assertEqual(type(result), int)
  61. @need_symbol('c_wchar')
  62. def test_wchar_result(self):
  63. f = dll._testfunc_i_bhilfd
  64. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
  65. f.restype = c_wchar
  66. result = f(0, 0, 0, 0, 0, 0)
  67. self.assertEqual(result, '\x00')
  68. def test_voidresult(self):
  69. f = dll._testfunc_v
  70. f.restype = None
  71. f.argtypes = [c_int, c_int, POINTER(c_int)]
  72. result = c_int()
  73. self.assertEqual(None, f(1, 2, byref(result)))
  74. self.assertEqual(result.value, 3)
  75. def test_intresult(self):
  76. f = dll._testfunc_i_bhilfd
  77. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
  78. f.restype = c_int
  79. result = f(1, 2, 3, 4, 5.0, 6.0)
  80. self.assertEqual(result, 21)
  81. self.assertEqual(type(result), int)
  82. result = f(-1, -2, -3, -4, -5.0, -6.0)
  83. self.assertEqual(result, -21)
  84. self.assertEqual(type(result), int)
  85. # If we declare the function to return a short,
  86. # is the high part split off?
  87. f.restype = c_short
  88. result = f(1, 2, 3, 4, 5.0, 6.0)
  89. self.assertEqual(result, 21)
  90. self.assertEqual(type(result), int)
  91. result = f(1, 2, 3, 0x10004, 5.0, 6.0)
  92. self.assertEqual(result, 21)
  93. self.assertEqual(type(result), int)
  94. # You cannot assign character format codes as restype any longer
  95. self.assertRaises(TypeError, setattr, f, "restype", "i")
  96. def test_floatresult(self):
  97. f = dll._testfunc_f_bhilfd
  98. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
  99. f.restype = c_float
  100. result = f(1, 2, 3, 4, 5.0, 6.0)
  101. self.assertEqual(result, 21)
  102. self.assertEqual(type(result), float)
  103. result = f(-1, -2, -3, -4, -5.0, -6.0)
  104. self.assertEqual(result, -21)
  105. self.assertEqual(type(result), float)
  106. def test_doubleresult(self):
  107. f = dll._testfunc_d_bhilfd
  108. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
  109. f.restype = c_double
  110. result = f(1, 2, 3, 4, 5.0, 6.0)
  111. self.assertEqual(result, 21)
  112. self.assertEqual(type(result), float)
  113. result = f(-1, -2, -3, -4, -5.0, -6.0)
  114. self.assertEqual(result, -21)
  115. self.assertEqual(type(result), float)
  116. def test_longdoubleresult(self):
  117. f = dll._testfunc_D_bhilfD
  118. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble]
  119. f.restype = c_longdouble
  120. result = f(1, 2, 3, 4, 5.0, 6.0)
  121. self.assertEqual(result, 21)
  122. self.assertEqual(type(result), float)
  123. result = f(-1, -2, -3, -4, -5.0, -6.0)
  124. self.assertEqual(result, -21)
  125. self.assertEqual(type(result), float)
  126. @need_symbol('c_longlong')
  127. def test_longlongresult(self):
  128. f = dll._testfunc_q_bhilfd
  129. f.restype = c_longlong
  130. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
  131. result = f(1, 2, 3, 4, 5.0, 6.0)
  132. self.assertEqual(result, 21)
  133. f = dll._testfunc_q_bhilfdq
  134. f.restype = c_longlong
  135. f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong]
  136. result = f(1, 2, 3, 4, 5.0, 6.0, 21)
  137. self.assertEqual(result, 42)
  138. def test_stringresult(self):
  139. f = dll._testfunc_p_p
  140. f.argtypes = None
  141. f.restype = c_char_p
  142. result = f(b"123")
  143. self.assertEqual(result, b"123")
  144. result = f(None)
  145. self.assertEqual(result, None)
  146. def test_pointers(self):
  147. f = dll._testfunc_p_p
  148. f.restype = POINTER(c_int)
  149. f.argtypes = [POINTER(c_int)]
  150. # This only works if the value c_int(42) passed to the
  151. # function is still alive while the pointer (the result) is
  152. # used.
  153. v = c_int(42)
  154. self.assertEqual(pointer(v).contents.value, 42)
  155. result = f(pointer(v))
  156. self.assertEqual(type(result), POINTER(c_int))
  157. self.assertEqual(result.contents.value, 42)
  158. # This on works...
  159. result = f(pointer(v))
  160. self.assertEqual(result.contents.value, v.value)
  161. p = pointer(c_int(99))
  162. result = f(p)
  163. self.assertEqual(result.contents.value, 99)
  164. arg = byref(v)
  165. result = f(arg)
  166. self.assertNotEqual(result.contents, v.value)
  167. self.assertRaises(ArgumentError, f, byref(c_short(22)))
  168. # It is dangerous, however, because you don't control the lifetime
  169. # of the pointer:
  170. result = f(byref(c_int(99)))
  171. self.assertNotEqual(result.contents, 99)
  172. def test_errors(self):
  173. f = dll._testfunc_p_p
  174. f.restype = c_int
  175. class X(Structure):
  176. _fields_ = [("y", c_int)]
  177. self.assertRaises(TypeError, f, X()) #cannot convert parameter
  178. ################################################################
  179. def test_shorts(self):
  180. f = dll._testfunc_callback_i_if
  181. args = []
  182. expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
  183. 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
  184. def callback(v):
  185. args.append(v)
  186. return v
  187. CallBack = CFUNCTYPE(c_int, c_int)
  188. cb = CallBack(callback)
  189. f(2**18, cb)
  190. self.assertEqual(args, expected)
  191. ################################################################
  192. def test_callbacks(self):
  193. f = dll._testfunc_callback_i_if
  194. f.restype = c_int
  195. f.argtypes = None
  196. MyCallback = CFUNCTYPE(c_int, c_int)
  197. def callback(value):
  198. #print "called back with", value
  199. return value
  200. cb = MyCallback(callback)
  201. result = f(-10, cb)
  202. self.assertEqual(result, -18)
  203. # test with prototype
  204. f.argtypes = [c_int, MyCallback]
  205. cb = MyCallback(callback)
  206. result = f(-10, cb)
  207. self.assertEqual(result, -18)
  208. AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
  209. # check that the prototype works: we call f with wrong
  210. # argument types
  211. cb = AnotherCallback(callback)
  212. self.assertRaises(ArgumentError, f, -10, cb)
  213. def test_callbacks_2(self):
  214. # Can also use simple datatypes as argument type specifiers
  215. # for the callback function.
  216. # In this case the call receives an instance of that type
  217. f = dll._testfunc_callback_i_if
  218. f.restype = c_int
  219. MyCallback = CFUNCTYPE(c_int, c_int)
  220. f.argtypes = [c_int, MyCallback]
  221. def callback(value):
  222. #print "called back with", value
  223. self.assertEqual(type(value), int)
  224. return value
  225. cb = MyCallback(callback)
  226. result = f(-10, cb)
  227. self.assertEqual(result, -18)
  228. @need_symbol('c_longlong')
  229. def test_longlong_callbacks(self):
  230. f = dll._testfunc_callback_q_qf
  231. f.restype = c_longlong
  232. MyCallback = CFUNCTYPE(c_longlong, c_longlong)
  233. f.argtypes = [c_longlong, MyCallback]
  234. def callback(value):
  235. self.assertIsInstance(value, int)
  236. return value & 0x7FFFFFFF
  237. cb = MyCallback(callback)
  238. self.assertEqual(13577625587, f(1000000000000, cb))
  239. def test_errors(self):
  240. self.assertRaises(AttributeError, getattr, dll, "_xxx_yyy")
  241. self.assertRaises(ValueError, c_int.in_dll, dll, "_xxx_yyy")
  242. def test_byval(self):
  243. # without prototype
  244. ptin = POINT(1, 2)
  245. ptout = POINT()
  246. # EXPORT int _testfunc_byval(point in, point *pout)
  247. result = dll._testfunc_byval(ptin, byref(ptout))
  248. got = result, ptout.x, ptout.y
  249. expected = 3, 1, 2
  250. self.assertEqual(got, expected)
  251. # with prototype
  252. ptin = POINT(101, 102)
  253. ptout = POINT()
  254. dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
  255. dll._testfunc_byval.restype = c_int
  256. result = dll._testfunc_byval(ptin, byref(ptout))
  257. got = result, ptout.x, ptout.y
  258. expected = 203, 101, 102
  259. self.assertEqual(got, expected)
  260. def test_struct_return_2H(self):
  261. class S2H(Structure):
  262. _fields_ = [("x", c_short),
  263. ("y", c_short)]
  264. dll.ret_2h_func.restype = S2H
  265. dll.ret_2h_func.argtypes = [S2H]
  266. inp = S2H(99, 88)
  267. s2h = dll.ret_2h_func(inp)
  268. self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
  269. @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
  270. def test_struct_return_2H_stdcall(self):
  271. class S2H(Structure):
  272. _fields_ = [("x", c_short),
  273. ("y", c_short)]
  274. windll.s_ret_2h_func.restype = S2H
  275. windll.s_ret_2h_func.argtypes = [S2H]
  276. s2h = windll.s_ret_2h_func(S2H(99, 88))
  277. self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
  278. def test_struct_return_8H(self):
  279. class S8I(Structure):
  280. _fields_ = [("a", c_int),
  281. ("b", c_int),
  282. ("c", c_int),
  283. ("d", c_int),
  284. ("e", c_int),
  285. ("f", c_int),
  286. ("g", c_int),
  287. ("h", c_int)]
  288. dll.ret_8i_func.restype = S8I
  289. dll.ret_8i_func.argtypes = [S8I]
  290. inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
  291. s8i = dll.ret_8i_func(inp)
  292. self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
  293. (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
  294. @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
  295. def test_struct_return_8H_stdcall(self):
  296. class S8I(Structure):
  297. _fields_ = [("a", c_int),
  298. ("b", c_int),
  299. ("c", c_int),
  300. ("d", c_int),
  301. ("e", c_int),
  302. ("f", c_int),
  303. ("g", c_int),
  304. ("h", c_int)]
  305. windll.s_ret_8i_func.restype = S8I
  306. windll.s_ret_8i_func.argtypes = [S8I]
  307. inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
  308. s8i = windll.s_ret_8i_func(inp)
  309. self.assertEqual(
  310. (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
  311. (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
  312. def test_sf1651235(self):
  313. # see http://www.python.org/sf/1651235
  314. proto = CFUNCTYPE(c_int, RECT, POINT)
  315. def callback(*args):
  316. return 0
  317. callback = proto(callback)
  318. self.assertRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT()))
  319. if __name__ == '__main__':
  320. unittest.main()