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