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