/Lib/ctypes/test/test_prototypes.py

http://unladen-swallow.googlecode.com/ · Python · 221 lines · 146 code · 47 blank · 28 comment · 11 complexity · 42652a9e5466dc7208b096e86da1953e MD5 · raw file

  1. from ctypes import *
  2. import unittest
  3. # IMPORTANT INFO:
  4. #
  5. # Consider this call:
  6. # func.restype = c_char_p
  7. # func(c_char_p("123"))
  8. # It returns
  9. # "123"
  10. #
  11. # WHY IS THIS SO?
  12. #
  13. # argument tuple (c_char_p("123"), ) is destroyed after the function
  14. # func is called, but NOT before the result is actually built.
  15. #
  16. # If the arglist would be destroyed BEFORE the result has been built,
  17. # the c_char_p("123") object would already have a zero refcount,
  18. # and the pointer passed to (and returned by) the function would
  19. # probably point to deallocated space.
  20. #
  21. # In this case, there would have to be an additional reference to the argument...
  22. import _ctypes_test
  23. testdll = CDLL(_ctypes_test.__file__)
  24. # Return machine address `a` as a (possibly long) non-negative integer.
  25. # Starting with Python 2.5, id(anything) is always non-negative, and
  26. # the ctypes addressof() inherits that via PyLong_FromVoidPtr().
  27. def positive_address(a):
  28. if a >= 0:
  29. return a
  30. # View the bits in `a` as unsigned instead.
  31. import struct
  32. num_bits = struct.calcsize("P") * 8 # num bits in native machine address
  33. a += 1L << num_bits
  34. assert a >= 0
  35. return a
  36. def c_wbuffer(init):
  37. n = len(init) + 1
  38. return (c_wchar * n)(*init)
  39. class CharPointersTestCase(unittest.TestCase):
  40. def setUp(self):
  41. func = testdll._testfunc_p_p
  42. func.restype = c_long
  43. func.argtypes = None
  44. def test_paramflags(self):
  45. # function returns c_void_p result,
  46. # and has a required parameter named 'input'
  47. prototype = CFUNCTYPE(c_void_p, c_void_p)
  48. func = prototype(("_testfunc_p_p", testdll),
  49. ((1, "input"),))
  50. try:
  51. func()
  52. except TypeError, details:
  53. self.failUnlessEqual(str(details), "required argument 'input' missing")
  54. else:
  55. self.fail("TypeError not raised")
  56. self.failUnlessEqual(func(None), None)
  57. self.failUnlessEqual(func(input=None), None)
  58. def test_int_pointer_arg(self):
  59. func = testdll._testfunc_p_p
  60. func.restype = c_long
  61. self.failUnlessEqual(0, func(0))
  62. ci = c_int(0)
  63. func.argtypes = POINTER(c_int),
  64. self.failUnlessEqual(positive_address(addressof(ci)),
  65. positive_address(func(byref(ci))))
  66. func.argtypes = c_char_p,
  67. self.assertRaises(ArgumentError, func, byref(ci))
  68. func.argtypes = POINTER(c_short),
  69. self.assertRaises(ArgumentError, func, byref(ci))
  70. func.argtypes = POINTER(c_double),
  71. self.assertRaises(ArgumentError, func, byref(ci))
  72. def test_POINTER_c_char_arg(self):
  73. func = testdll._testfunc_p_p
  74. func.restype = c_char_p
  75. func.argtypes = POINTER(c_char),
  76. self.failUnlessEqual(None, func(None))
  77. self.failUnlessEqual("123", func("123"))
  78. self.failUnlessEqual(None, func(c_char_p(None)))
  79. self.failUnlessEqual("123", func(c_char_p("123")))
  80. self.failUnlessEqual("123", func(c_buffer("123")))
  81. ca = c_char("a")
  82. self.failUnlessEqual("a", func(pointer(ca))[0])
  83. self.failUnlessEqual("a", func(byref(ca))[0])
  84. def test_c_char_p_arg(self):
  85. func = testdll._testfunc_p_p
  86. func.restype = c_char_p
  87. func.argtypes = c_char_p,
  88. self.failUnlessEqual(None, func(None))
  89. self.failUnlessEqual("123", func("123"))
  90. self.failUnlessEqual(None, func(c_char_p(None)))
  91. self.failUnlessEqual("123", func(c_char_p("123")))
  92. self.failUnlessEqual("123", func(c_buffer("123")))
  93. ca = c_char("a")
  94. self.failUnlessEqual("a", func(pointer(ca))[0])
  95. self.failUnlessEqual("a", func(byref(ca))[0])
  96. def test_c_void_p_arg(self):
  97. func = testdll._testfunc_p_p
  98. func.restype = c_char_p
  99. func.argtypes = c_void_p,
  100. self.failUnlessEqual(None, func(None))
  101. self.failUnlessEqual("123", func("123"))
  102. self.failUnlessEqual("123", func(c_char_p("123")))
  103. self.failUnlessEqual(None, func(c_char_p(None)))
  104. self.failUnlessEqual("123", func(c_buffer("123")))
  105. ca = c_char("a")
  106. self.failUnlessEqual("a", func(pointer(ca))[0])
  107. self.failUnlessEqual("a", func(byref(ca))[0])
  108. func(byref(c_int()))
  109. func(pointer(c_int()))
  110. func((c_int * 3)())
  111. try:
  112. func.restype = c_wchar_p
  113. except NameError:
  114. pass
  115. else:
  116. self.failUnlessEqual(None, func(c_wchar_p(None)))
  117. self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
  118. def test_instance(self):
  119. func = testdll._testfunc_p_p
  120. func.restype = c_void_p
  121. class X:
  122. _as_parameter_ = None
  123. func.argtypes = c_void_p,
  124. self.failUnlessEqual(None, func(X()))
  125. func.argtypes = None
  126. self.failUnlessEqual(None, func(X()))
  127. try:
  128. c_wchar
  129. except NameError:
  130. pass
  131. else:
  132. class WCharPointersTestCase(unittest.TestCase):
  133. def setUp(self):
  134. func = testdll._testfunc_p_p
  135. func.restype = c_int
  136. func.argtypes = None
  137. def test_POINTER_c_wchar_arg(self):
  138. func = testdll._testfunc_p_p
  139. func.restype = c_wchar_p
  140. func.argtypes = POINTER(c_wchar),
  141. self.failUnlessEqual(None, func(None))
  142. self.failUnlessEqual(u"123", func(u"123"))
  143. self.failUnlessEqual(None, func(c_wchar_p(None)))
  144. self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
  145. self.failUnlessEqual(u"123", func(c_wbuffer(u"123")))
  146. ca = c_wchar("a")
  147. self.failUnlessEqual(u"a", func(pointer(ca))[0])
  148. self.failUnlessEqual(u"a", func(byref(ca))[0])
  149. def test_c_wchar_p_arg(self):
  150. func = testdll._testfunc_p_p
  151. func.restype = c_wchar_p
  152. func.argtypes = c_wchar_p,
  153. c_wchar_p.from_param(u"123")
  154. self.failUnlessEqual(None, func(None))
  155. self.failUnlessEqual("123", func(u"123"))
  156. self.failUnlessEqual(None, func(c_wchar_p(None)))
  157. self.failUnlessEqual("123", func(c_wchar_p("123")))
  158. # XXX Currently, these raise TypeErrors, although they shouldn't:
  159. self.failUnlessEqual("123", func(c_wbuffer("123")))
  160. ca = c_wchar("a")
  161. self.failUnlessEqual("a", func(pointer(ca))[0])
  162. self.failUnlessEqual("a", func(byref(ca))[0])
  163. class ArrayTest(unittest.TestCase):
  164. def test(self):
  165. func = testdll._testfunc_ai8
  166. func.restype = POINTER(c_int)
  167. func.argtypes = c_int * 8,
  168. func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8))
  169. # This did crash before:
  170. def func(): pass
  171. CFUNCTYPE(None, c_int * 3)(func)
  172. ################################################################
  173. if __name__ == '__main__':
  174. unittest.main()