14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport unittest, sys
24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom ctypes import *
44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport _ctypes_test
54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                 c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float]
84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaopython_types = [int, int, int, int, int, long,
94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                int, long, long, long, float, float]
104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PointersTestCase(unittest.TestCase):
124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_pointer_crash(self):
144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class A(POINTER(c_ulong)):
164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            pass
174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        POINTER(c_ulong)(c_ulong(22))
194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Pointer can't set contents: has no _type_
204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, A, c_ulong(33))
214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_pass_pointers(self):
234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dll = CDLL(_ctypes_test.__file__)
244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func = dll._testfunc_p_p
254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func.restype = c_long
264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        i = c_int(12345678)
284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        func.argtypes = (POINTER(c_int),)
294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        address = func(byref(i))
304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(c_int.from_address(address).value, 12345678)
314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func.restype = POINTER(c_int)
334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        res = func(pointer(i))
344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(res.contents.value, 12345678)
354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(res[0], 12345678)
364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_change_pointers(self):
384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dll = CDLL(_ctypes_test.__file__)
394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func = dll._testfunc_p_p
404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        i = c_int(87654)
424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func.restype = POINTER(c_int)
434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func.argtypes = (POINTER(c_int),)
444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        res = func(pointer(i))
464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(res[0], 87654)
474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(res.contents.value, 87654)
484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # C code: *res = 54345
504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        res[0] = 54345
514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(i.value, 54345)
524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # C code:
544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #   int x = 12321;
554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #   res = &x
564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        res.contents = c_int(12321)
574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(i.value, 54345)
584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_callbacks_with_pointers(self):
604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # a function type receiving a pointer
614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.result = []
644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def func(arg):
664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            for i in range(10):
674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##                print arg[i],
684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.result.append(arg[i])
694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##            print
704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return 0
714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        callback = PROTOTYPE(func)
724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dll = CDLL(_ctypes_test.__file__)
744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # This function expects a function pointer,
754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # and calls this with an integer pointer as parameter.
764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # The int pointer points to a table containing the numbers 1..10
774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        doit = dll._testfunc_callback_with_pointer
784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        i = c_int(42)
804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        callback(byref(i))
814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        self.assertTrue(i.value == 84)
824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        doit(callback)
844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        print self.result
854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        doit(callback)
864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        print self.result
874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_basics(self):
894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        from operator import delitem
904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        for ct, pt in zip(ctype_types, python_types):
914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            i = ct(42)
924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = pointer(i)
934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##            print type(p.contents), ct
944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertTrue(type(p.contents) is ct)
954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # p.contents is the same as p[0]
964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##            print p.contents
974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##            self.assertTrue(p.contents == 42)
984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##            self.assertTrue(p[0] == 42)
994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertRaises(TypeError, delitem, p, 0)
1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_from_address(self):
1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        from array import array
1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        a = array('i', [100, 200, 300, 400, 500])
1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        addr = a.buffer_info()[0]
1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = POINTER(POINTER(c_int))
1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        print dir(p)
1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        print p.from_address
1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao##        print p.from_address(addr)[0][0]
1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_other(self):
1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class Table(Structure):
1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            _fields_ = [("a", c_int),
1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        ("b", c_int),
1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        ("c", c_int)]
1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pt = pointer(Table(1, 2, 3))
1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(pt.contents.a, 1)
1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(pt.contents.b, 2)
1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(pt.contents.c, 3)
1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pt.contents.c = 33
1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        from ctypes import _pointer_type_cache
1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        del _pointer_type_cache[Table]
1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_basic(self):
1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = pointer(c_int(42))
1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Although a pointer can be indexed, it ha no length
1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, len, p)
1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p[0], 42)
1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.contents.value, 42)
1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_charpp(self):
1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        """Test that a character pointer-to-pointer is correctly passed"""
1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dll = CDLL(_ctypes_test.__file__)
1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func = dll._testfunc_c_p_p
1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        func.restype = c_char_p
1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        argv = (c_char_p * 2)()
1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        argc = c_int( 2 )
1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        argv[0] = 'hello'
1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        argv[1] = 'world'
1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        result = func( byref(argc), argv )
1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert result == 'world', result
1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_bug_1467852(self):
1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702
1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        x = c_int(5)
1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dummy = []
1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        for i in range(32000):
1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            dummy.append(c_int(i))
1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        y = c_int(6)
1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = pointer(x)
1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pp = pointer(p)
1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        q = pointer(y)
1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pp[0] = q         # <==
1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p[0], 6)
1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_c_void_p(self):
1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470
1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if sizeof(c_void_p) == 4:
1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(c_void_p(0xFFFFFFFFL).value,
1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                 c_void_p(-1).value)
1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                 c_void_p(-1).value)
1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        elif sizeof(c_void_p) == 8:
1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(c_void_p(0xFFFFFFFFL).value,
1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                 0xFFFFFFFFL)
1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                 c_void_p(-1).value)
1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFFL).value,
1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                 c_void_p(-1).value)
1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted
1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, c_void_p, object()) # nor other objects
1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_pointers_bool(self):
1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # NULL pointers have a boolean False value, non-NULL pointers True.
1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(bool(POINTER(c_int)()), False)
1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(bool(pointer(c_int())), True)
1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(bool(CFUNCTYPE(None)(0)), False)
1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(bool(CFUNCTYPE(None)(42)), True)
1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # COM methods are boolean True:
1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if sys.platform == "win32":
1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            mth = WINFUNCTYPE(None)(42, "name", (), None)
1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(bool(mth), True)
1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif __name__ == '__main__':
1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    unittest.main()
193