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