1import unittest, sys 2 3from ctypes import * 4import _ctypes_test 5 6ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, 7 c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float] 8python_types = [int, int, int, int, int, int, 9 int, int, int, int, float, float] 10 11class PointersTestCase(unittest.TestCase): 12 13 def test_pointer_crash(self): 14 15 class A(POINTER(c_ulong)): 16 pass 17 18 POINTER(c_ulong)(c_ulong(22)) 19 # Pointer can't set contents: has no _type_ 20 self.assertRaises(TypeError, A, c_ulong(33)) 21 22 def test_pass_pointers(self): 23 dll = CDLL(_ctypes_test.__file__) 24 func = dll._testfunc_p_p 25 if sizeof(c_longlong) == sizeof(c_void_p): 26 func.restype = c_longlong 27 else: 28 func.restype = c_long 29 30 i = c_int(12345678) 31## func.argtypes = (POINTER(c_int),) 32 address = func(byref(i)) 33 self.assertEqual(c_int.from_address(address).value, 12345678) 34 35 func.restype = POINTER(c_int) 36 res = func(pointer(i)) 37 self.assertEqual(res.contents.value, 12345678) 38 self.assertEqual(res[0], 12345678) 39 40 def test_change_pointers(self): 41 dll = CDLL(_ctypes_test.__file__) 42 func = dll._testfunc_p_p 43 44 i = c_int(87654) 45 func.restype = POINTER(c_int) 46 func.argtypes = (POINTER(c_int),) 47 48 res = func(pointer(i)) 49 self.assertEqual(res[0], 87654) 50 self.assertEqual(res.contents.value, 87654) 51 52 # C code: *res = 54345 53 res[0] = 54345 54 self.assertEqual(i.value, 54345) 55 56 # C code: 57 # int x = 12321; 58 # res = &x 59 x = c_int(12321) 60 res.contents = x 61 self.assertEqual(i.value, 54345) 62 63 x.value = -99 64 self.assertEqual(res.contents.value, -99) 65 66 def test_callbacks_with_pointers(self): 67 # a function type receiving a pointer 68 PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int)) 69 70 self.result = [] 71 72 def func(arg): 73 for i in range(10): 74## print arg[i], 75 self.result.append(arg[i]) 76## print 77 return 0 78 callback = PROTOTYPE(func) 79 80 dll = CDLL(_ctypes_test.__file__) 81 # This function expects a function pointer, 82 # and calls this with an integer pointer as parameter. 83 # The int pointer points to a table containing the numbers 1..10 84 doit = dll._testfunc_callback_with_pointer 85 86## i = c_int(42) 87## callback(byref(i)) 88## self.assertEqual(i.value, 84) 89 90 doit(callback) 91## print self.result 92 doit(callback) 93## print self.result 94 95 def test_basics(self): 96 from operator import delitem 97 for ct, pt in zip(ctype_types, python_types): 98 i = ct(42) 99 p = pointer(i) 100## print type(p.contents), ct 101 self.assertIs(type(p.contents), ct) 102 # p.contents is the same as p[0] 103## print p.contents 104## self.assertEqual(p.contents, 42) 105## self.assertEqual(p[0], 42) 106 107 self.assertRaises(TypeError, delitem, p, 0) 108 109 def test_from_address(self): 110 from array import array 111 a = array('i', [100, 200, 300, 400, 500]) 112 addr = a.buffer_info()[0] 113 114 p = POINTER(POINTER(c_int)) 115## print dir(p) 116## print p.from_address 117## print p.from_address(addr)[0][0] 118 119 def test_other(self): 120 class Table(Structure): 121 _fields_ = [("a", c_int), 122 ("b", c_int), 123 ("c", c_int)] 124 125 pt = pointer(Table(1, 2, 3)) 126 127 self.assertEqual(pt.contents.a, 1) 128 self.assertEqual(pt.contents.b, 2) 129 self.assertEqual(pt.contents.c, 3) 130 131 pt.contents.c = 33 132 133 from ctypes import _pointer_type_cache 134 del _pointer_type_cache[Table] 135 136 def test_basic(self): 137 p = pointer(c_int(42)) 138 # Although a pointer can be indexed, it has no length 139 self.assertRaises(TypeError, len, p) 140 self.assertEqual(p[0], 42) 141 self.assertEqual(p[0:1], [42]) 142 self.assertEqual(p.contents.value, 42) 143 144 def test_charpp(self): 145 """Test that a character pointer-to-pointer is correctly passed""" 146 dll = CDLL(_ctypes_test.__file__) 147 func = dll._testfunc_c_p_p 148 func.restype = c_char_p 149 argv = (c_char_p * 2)() 150 argc = c_int( 2 ) 151 argv[0] = b'hello' 152 argv[1] = b'world' 153 result = func( byref(argc), argv ) 154 self.assertEqual(result, b'world') 155 156 def test_bug_1467852(self): 157 # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 158 x = c_int(5) 159 dummy = [] 160 for i in range(32000): 161 dummy.append(c_int(i)) 162 y = c_int(6) 163 p = pointer(x) 164 pp = pointer(p) 165 q = pointer(y) 166 pp[0] = q # <== 167 self.assertEqual(p[0], 6) 168 def test_c_void_p(self): 169 # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470 170 if sizeof(c_void_p) == 4: 171 self.assertEqual(c_void_p(0xFFFFFFFF).value, 172 c_void_p(-1).value) 173 self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFF).value, 174 c_void_p(-1).value) 175 elif sizeof(c_void_p) == 8: 176 self.assertEqual(c_void_p(0xFFFFFFFF).value, 177 0xFFFFFFFF) 178 self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFF).value, 179 c_void_p(-1).value) 180 self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFF).value, 181 c_void_p(-1).value) 182 183 self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted 184 self.assertRaises(TypeError, c_void_p, object()) # nor other objects 185 186 def test_pointers_bool(self): 187 # NULL pointers have a boolean False value, non-NULL pointers True. 188 self.assertEqual(bool(POINTER(c_int)()), False) 189 self.assertEqual(bool(pointer(c_int())), True) 190 191 self.assertEqual(bool(CFUNCTYPE(None)(0)), False) 192 self.assertEqual(bool(CFUNCTYPE(None)(42)), True) 193 194 # COM methods are boolean True: 195 if sys.platform == "win32": 196 mth = WINFUNCTYPE(None)(42, "name", (), None) 197 self.assertEqual(bool(mth), True) 198 199 def test_pointer_type_name(self): 200 LargeNamedType = type('T' * 2 ** 25, (Structure,), {}) 201 self.assertTrue(POINTER(LargeNamedType)) 202 203 # to not leak references, we must clean _pointer_type_cache 204 from ctypes import _pointer_type_cache 205 del _pointer_type_cache[LargeNamedType] 206 207 def test_pointer_type_str_name(self): 208 large_string = 'T' * 2 ** 25 209 P = POINTER(large_string) 210 self.assertTrue(P) 211 212 # to not leak references, we must clean _pointer_type_cache 213 from ctypes import _pointer_type_cache 214 del _pointer_type_cache[id(P)] 215 216 217if __name__ == '__main__': 218 unittest.main() 219