/Lib/ctypes/test/test_functions.py

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