test_pointers.py revision e8d09e581816aa7fdb812801c79e8f6bc55dc134
1babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerimport unittest
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]
8babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerpython_types = [int, int, int, int, int, long,
9babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller                int, long, long, long, 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_
20babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessRaises(TypeError, A, c_ulong(33))
21babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
22babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_pass_pointers(self):
23babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        dll = cdll.load(_ctypes_test.__file__)
24babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func = dll._testfunc_p_p
25babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func.restype = c_long
26babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
27babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        i = c_int(12345678)
28babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        func.argtypes = (POINTER(c_int),)
29babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        address = func(byref(i))
30babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(c_int.from_address(address).value, 12345678)
31babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
32babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func.restype = POINTER(c_int)
33babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        res = func(pointer(i))
34babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(res.contents.value, 12345678)
35babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(res[0], 12345678)
36babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
37babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_change_pointers(self):
38babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        dll = cdll.load(_ctypes_test.__file__)
39babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func = dll._testfunc_p_p
40babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
41babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        i = c_int(87654)
42babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func.restype = POINTER(c_int)
43babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func.argtypes = (POINTER(c_int),)
44babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
45babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        res = func(pointer(i))
46babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(res[0], 87654)
47babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(res.contents.value, 87654)
48babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
49babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # C code: *res = 54345
50babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        res[0] = 54345
51babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(i.value, 54345)
52babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
53babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # C code:
54babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        #   int x = 12321;
55babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        #   res = &x
56babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        res.contents = c_int(12321)
57babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(i.value, 54345)
58babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
59babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_callbacks_with_pointers(self):
60babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # a function type receiving a pointer
61babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
62babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
63babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.result = []
64babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
65babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        def func(arg):
66babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            for i in range(10):
67babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##                print arg[i],
68babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller                self.result.append(arg[i])
69babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##            print
70babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            return 0
71babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        callback = PROTOTYPE(func)
72babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
73babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        dll = cdll.load(_ctypes_test.__file__)
74babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # This function expects a function pointer,
75babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # and calls this with an integer pointer as parameter.
76babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # The int pointer points to a table containing the numbers 1..10
77babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        doit = dll._testfunc_callback_with_pointer
78babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
79babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        i = c_int(42)
80babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        callback(byref(i))
81babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        self.failUnless(i.value == 84)
82babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
83babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        doit(callback)
84babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        print self.result
85babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        doit(callback)
86babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        print self.result
87e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters
88babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_basics(self):
89babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        from operator import delitem
90babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        for ct, pt in zip(ctype_types, python_types):
91babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            i = ct(42)
92babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            p = pointer(i)
93babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##            print type(p.contents), ct
94babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            self.failUnless(type(p.contents) is ct)
95babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            # p.contents is the same as p[0]
96babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##            print p.contents
97babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##            self.failUnless(p.contents == 42)
98babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##            self.failUnless(p[0] == 42)
99babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
100babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            self.assertRaises(TypeError, delitem, p, 0)
101babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
102babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_from_address(self):
103babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        from array import array
104babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        a = array('i', [100, 200, 300, 400, 500])
105babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        addr = a.buffer_info()[0]
106babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
107babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        p = POINTER(POINTER(c_int))
108babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        print dir(p)
109babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        print p.from_address
110babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller##        print p.from_address(addr)[0][0]
111babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
112babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_other(self):
113babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        class Table(Structure):
114babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            _fields_ = [("a", c_int),
115babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller                        ("b", c_int),
116babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller                        ("c", c_int)]
117babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
118babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        pt = pointer(Table(1, 2, 3))
119babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
120babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(pt.contents.a, 1)
121babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(pt.contents.b, 2)
122babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(pt.contents.c, 3)
123babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
124babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        pt.contents.c = 33
125babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
126babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        from ctypes import _pointer_type_cache
127babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        del _pointer_type_cache[Table]
128babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
129babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_basic(self):
130babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        p = pointer(c_int(42))
131babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # Although a pointer can be indexed, it ha no length
132babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.assertRaises(TypeError, len, p)
133babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(p[0], 42)
134babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(p.contents.value, 42)
135e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters
136babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_incomplete(self):
137babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        lpcell = POINTER("cell")
138babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        class cell(Structure):
139babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            _fields_ = [("value", c_int),
140babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller                        ("next", lpcell)]
141babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        SetPointerType(lpcell, cell)
142babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
143babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        # Make a structure containing a pointer to itself:
144babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        c = cell()
145babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        c.value = 42
146babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        c.next = pointer(c)
147babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
148babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        result = []
149babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        for i in range(8):
150babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            result.append(c.value)
151babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller            c = c.next[0]
152babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        self.failUnlessEqual(result, [42] * 8)
153babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
154babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        from ctypes import _pointer_type_cache
155babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        del _pointer_type_cache[cell]
156babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
157babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    def test_charpp( self ):
158babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        """Test that a character pointer-to-pointer is correctly passed"""
159babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        dll = cdll.load(_ctypes_test.__file__)
160babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func = dll._testfunc_c_p_p
161babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        func.restype = c_char_p
162babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        argv = (c_char_p * 2)()
163babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        argc = c_int( 2 )
164babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        argv[0] = 'hello'
165babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        argv[1] = 'world'
166babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        result = func( byref(argc), argv )
167babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller        assert result == 'world', result
168babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller
169e8d09e581816aa7fdb812801c79e8f6bc55dc134Tim Peters
170babddfca758abe34ff12023f63b18d745fae7ca9Thomas Hellerif __name__ == '__main__':
171babddfca758abe34ff12023f63b18d745fae7ca9Thomas Heller    unittest.main()
172