1f5049fc8c65ca45a3d42de400be57353b42f1d61Thomas Hellerimport unittest, sys 2babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 3babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerfrom ctypes import * 4babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerimport _ctypes_test 5babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 6babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, 7babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float] 8e2a383d062434c05b73031f0da57fe82b9da8942Guido van Rossumpython_types = [int, int, int, int, int, int, 9e2a383d062434c05b73031f0da57fe82b9da8942Guido van Rossum int, int, int, int, float, float] 10babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 11babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerclass PointersTestCase(unittest.TestCase): 12babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 13babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_pointer_crash(self): 14e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters 15babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller class A(POINTER(c_ulong)): 16babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller pass 17babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 18babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller POINTER(c_ulong)(c_ulong(22)) 19babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # Pointer can't set contents: has no _type_ 20c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertRaises(TypeError, A, c_ulong(33)) 21babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 22babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_pass_pointers(self): 23477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters dll = CDLL(_ctypes_test.__file__) 24babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func = dll._testfunc_p_p 2553683965aaf2895fbdb851e07436c6f86b48d0dcSteve Dower if sizeof(c_longlong) == sizeof(c_void_p): 2653683965aaf2895fbdb851e07436c6f86b48d0dcSteve Dower func.restype = c_longlong 2753683965aaf2895fbdb851e07436c6f86b48d0dcSteve Dower else: 2853683965aaf2895fbdb851e07436c6f86b48d0dcSteve Dower func.restype = c_long 29babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 30babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller i = c_int(12345678) 31babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## func.argtypes = (POINTER(c_int),) 32babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller address = func(byref(i)) 33c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(c_int.from_address(address).value, 12345678) 34babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 35babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func.restype = POINTER(c_int) 36babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller res = func(pointer(i)) 37c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(res.contents.value, 12345678) 38c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(res[0], 12345678) 39babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 40babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_change_pointers(self): 41477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters dll = CDLL(_ctypes_test.__file__) 42babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func = dll._testfunc_p_p 43babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 44babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller i = c_int(87654) 45babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func.restype = POINTER(c_int) 46babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func.argtypes = (POINTER(c_int),) 47babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 48babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller res = func(pointer(i)) 49c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(res[0], 87654) 50c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(res.contents.value, 87654) 51babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 52babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # C code: *res = 54345 53babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller res[0] = 54345 54c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(i.value, 54345) 55babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 56babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # C code: 57babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # int x = 12321; 58babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # res = &x 5934360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter x = c_int(12321) 6034360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter res.contents = x 61c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(i.value, 54345) 62babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 6334360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter x.value = -99 6434360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter self.assertEqual(res.contents.value, -99) 6534360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter 66babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_callbacks_with_pointers(self): 67babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # a function type receiving a pointer 68babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int)) 69babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 70babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller self.result = [] 71babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 72babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def func(arg): 73babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller for i in range(10): 74babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print arg[i], 75babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller self.result.append(arg[i]) 76babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print 77babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller return 0 78babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller callback = PROTOTYPE(func) 79babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 80477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters dll = CDLL(_ctypes_test.__file__) 81babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # This function expects a function pointer, 82babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # and calls this with an integer pointer as parameter. 83babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # The int pointer points to a table containing the numbers 1..10 84babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller doit = dll._testfunc_callback_with_pointer 85babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 86babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## i = c_int(42) 87babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## callback(byref(i)) 887c5e24f948e6ce33e21b09833f8fe3a8eb1530acSerhiy Storchaka## self.assertEqual(i.value, 84) 89babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 90babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller doit(callback) 91babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print self.result 92babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller doit(callback) 93babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print self.result 94e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters 95babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_basics(self): 96babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller from operator import delitem 97babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller for ct, pt in zip(ctype_types, python_types): 98babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller i = ct(42) 99babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller p = pointer(i) 100babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print type(p.contents), ct 1017c5e24f948e6ce33e21b09833f8fe3a8eb1530acSerhiy Storchaka self.assertIs(type(p.contents), ct) 102babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller # p.contents is the same as p[0] 103babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print p.contents 1047c5e24f948e6ce33e21b09833f8fe3a8eb1530acSerhiy Storchaka## self.assertEqual(p.contents, 42) 1057c5e24f948e6ce33e21b09833f8fe3a8eb1530acSerhiy Storchaka## self.assertEqual(p[0], 42) 106babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 107babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller self.assertRaises(TypeError, delitem, p, 0) 108babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 109babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_from_address(self): 110babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller from array import array 111babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller a = array('i', [100, 200, 300, 400, 500]) 112babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller addr = a.buffer_info()[0] 113babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 114babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller p = POINTER(POINTER(c_int)) 115babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print dir(p) 116babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print p.from_address 117babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller## print p.from_address(addr)[0][0] 118babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 119babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_other(self): 120babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller class Table(Structure): 121babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller _fields_ = [("a", c_int), 122babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller ("b", c_int), 123babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller ("c", c_int)] 124babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 125babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller pt = pointer(Table(1, 2, 3)) 126babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 127c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(pt.contents.a, 1) 128c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(pt.contents.b, 2) 129c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(pt.contents.c, 3) 130babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 131babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller pt.contents.c = 33 132babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 133babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller from ctypes import _pointer_type_cache 134babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller del _pointer_type_cache[Table] 135babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 136babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller def test_basic(self): 137babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller p = pointer(c_int(42)) 13834360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter # Although a pointer can be indexed, it has no length 139babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller self.assertRaises(TypeError, len, p) 140c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(p[0], 42) 14134360c8e09f51075fec0c673b2674d20bed33bf5Martin Panter self.assertEqual(p[0:1], [42]) 142c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(p.contents.value, 42) 143e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters 14473e5a5b65d66f4fba9c4f626bcd6400f4a7215e6Thomas Wouters def test_charpp(self): 145babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller """Test that a character pointer-to-pointer is correctly passed""" 146477c8d5e70240744d24631b18341ad892c8a8e1cThomas Wouters dll = CDLL(_ctypes_test.__file__) 147babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func = dll._testfunc_c_p_p 148babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller func.restype = c_char_p 149babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller argv = (c_char_p * 2)() 150babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller argc = c_int( 2 ) 1518b939526215754a0317353f9e8d9ed85636101a0Thomas Heller argv[0] = b'hello' 1528b939526215754a0317353f9e8d9ed85636101a0Thomas Heller argv[1] = b'world' 153babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller result = func( byref(argc), argv ) 1548b939526215754a0317353f9e8d9ed85636101a0Thomas Heller self.assertEqual(result, b'world') 155babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller 15649fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters def test_bug_1467852(self): 15749fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 15849fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters x = c_int(5) 15949fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters dummy = [] 16049fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters for i in range(32000): 16149fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters dummy.append(c_int(i)) 16249fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters y = c_int(6) 16349fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters p = pointer(x) 16449fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters pp = pointer(p) 16549fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters q = pointer(y) 16649fd7fa4431da299196d74087df4a04f99f9c46fThomas Wouters pp[0] = q # <== 167c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(p[0], 6) 1680e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters def test_c_void_p(self): 1690e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470 1700e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters if sizeof(c_void_p) == 4: 171c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(c_void_p(0xFFFFFFFF).value, 1720e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters c_void_p(-1).value) 173c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFF).value, 1740e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters c_void_p(-1).value) 1750e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters elif sizeof(c_void_p) == 8: 176c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(c_void_p(0xFFFFFFFF).value, 177e2a383d062434c05b73031f0da57fe82b9da8942Guido van Rossum 0xFFFFFFFF) 178c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFF).value, 1790e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters c_void_p(-1).value) 180c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFF).value, 1810e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters c_void_p(-1).value) 1820e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters 1830e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted 1840e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters self.assertRaises(TypeError, c_void_p, object()) # nor other objects 185e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters 1867dca3ebc97661da9fe2945b9c65d58c234d10629Thomas Heller def test_pointers_bool(self): 1877dca3ebc97661da9fe2945b9c65d58c234d10629Thomas Heller # NULL pointers have a boolean False value, non-NULL pointers True. 188c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(bool(POINTER(c_int)()), False) 189c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(bool(pointer(c_int())), True) 1907dca3ebc97661da9fe2945b9c65d58c234d10629Thomas Heller 191c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(bool(CFUNCTYPE(None)(0)), False) 192c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(bool(CFUNCTYPE(None)(42)), True) 1937dca3ebc97661da9fe2945b9c65d58c234d10629Thomas Heller 194f5049fc8c65ca45a3d42de400be57353b42f1d61Thomas Heller # COM methods are boolean True: 195f5049fc8c65ca45a3d42de400be57353b42f1d61Thomas Heller if sys.platform == "win32": 196f5049fc8c65ca45a3d42de400be57353b42f1d61Thomas Heller mth = WINFUNCTYPE(None)(42, "name", (), None) 197c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson self.assertEqual(bool(mth), True) 198f5049fc8c65ca45a3d42de400be57353b42f1d61Thomas Heller 199817905b2393b03e035d2bbfc8d92b7bbeaddb118R David Murray def test_pointer_type_name(self): 2009db55004a1bc0c0b3efca69dcd577ff58a86ea16Serhiy Storchaka LargeNamedType = type('T' * 2 ** 25, (Structure,), {}) 201817905b2393b03e035d2bbfc8d92b7bbeaddb118R David Murray self.assertTrue(POINTER(LargeNamedType)) 202817905b2393b03e035d2bbfc8d92b7bbeaddb118R David Murray 203b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka # to not leak references, we must clean _pointer_type_cache 204b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka from ctypes import _pointer_type_cache 205b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka del _pointer_type_cache[LargeNamedType] 206b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka 207817905b2393b03e035d2bbfc8d92b7bbeaddb118R David Murray def test_pointer_type_str_name(self): 2089db55004a1bc0c0b3efca69dcd577ff58a86ea16Serhiy Storchaka large_string = 'T' * 2 ** 25 209b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka P = POINTER(large_string) 210b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka self.assertTrue(P) 211b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka 212b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka # to not leak references, we must clean _pointer_type_cache 213b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka from ctypes import _pointer_type_cache 214b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka del _pointer_type_cache[id(P)] 215b63902a74834e3e7d15356ff60e017ee6efba2a7Serhiy Storchaka 216817905b2393b03e035d2bbfc8d92b7bbeaddb118R David Murray 217babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerif __name__ == '__main__': 218babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller unittest.main() 219