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