• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import unittest
2from ctypes import *
3from ctypes.test import need_symbol
4import _ctypes_test
5
6dll = CDLL(_ctypes_test.__file__)
7
8try:
9    CALLBACK_FUNCTYPE = WINFUNCTYPE
10except NameError:
11    # fake to enable this test on Linux
12    CALLBACK_FUNCTYPE = CFUNCTYPE
13
14class POINT(Structure):
15    _fields_ = [("x", c_int), ("y", c_int)]
16
17class BasicWrapTestCase(unittest.TestCase):
18    def wrap(self, param):
19        return param
20
21    @need_symbol('c_wchar')
22    def test_wchar_parm(self):
23        f = dll._testfunc_i_bhilfd
24        f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
25        result = f(self.wrap(1), self.wrap("x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0))
26        self.assertEqual(result, 139)
27        self.assertIs(type(result), int)
28
29    def test_pointers(self):
30        f = dll._testfunc_p_p
31        f.restype = POINTER(c_int)
32        f.argtypes = [POINTER(c_int)]
33
34        # This only works if the value c_int(42) passed to the
35        # function is still alive while the pointer (the result) is
36        # used.
37
38        v = c_int(42)
39
40        self.assertEqual(pointer(v).contents.value, 42)
41        result = f(self.wrap(pointer(v)))
42        self.assertEqual(type(result), POINTER(c_int))
43        self.assertEqual(result.contents.value, 42)
44
45        # This on works...
46        result = f(self.wrap(pointer(v)))
47        self.assertEqual(result.contents.value, v.value)
48
49        p = pointer(c_int(99))
50        result = f(self.wrap(p))
51        self.assertEqual(result.contents.value, 99)
52
53    def test_shorts(self):
54        f = dll._testfunc_callback_i_if
55
56        args = []
57        expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
58                    1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
59
60        def callback(v):
61            args.append(v)
62            return v
63
64        CallBack = CFUNCTYPE(c_int, c_int)
65
66        cb = CallBack(callback)
67        f(self.wrap(2**18), self.wrap(cb))
68        self.assertEqual(args, expected)
69
70    ################################################################
71
72    def test_callbacks(self):
73        f = dll._testfunc_callback_i_if
74        f.restype = c_int
75        f.argtypes = None
76
77        MyCallback = CFUNCTYPE(c_int, c_int)
78
79        def callback(value):
80            #print "called back with", value
81            return value
82
83        cb = MyCallback(callback)
84
85        result = f(self.wrap(-10), self.wrap(cb))
86        self.assertEqual(result, -18)
87
88        # test with prototype
89        f.argtypes = [c_int, MyCallback]
90        cb = MyCallback(callback)
91
92        result = f(self.wrap(-10), self.wrap(cb))
93        self.assertEqual(result, -18)
94
95        result = f(self.wrap(-10), self.wrap(cb))
96        self.assertEqual(result, -18)
97
98        AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int)
99
100        # check that the prototype works: we call f with wrong
101        # argument types
102        cb = AnotherCallback(callback)
103        self.assertRaises(ArgumentError, f, self.wrap(-10), self.wrap(cb))
104
105    def test_callbacks_2(self):
106        # Can also use simple datatypes as argument type specifiers
107        # for the callback function.
108        # In this case the call receives an instance of that type
109        f = dll._testfunc_callback_i_if
110        f.restype = c_int
111
112        MyCallback = CFUNCTYPE(c_int, c_int)
113
114        f.argtypes = [c_int, MyCallback]
115
116        def callback(value):
117            #print "called back with", value
118            self.assertEqual(type(value), int)
119            return value
120
121        cb = MyCallback(callback)
122        result = f(self.wrap(-10), self.wrap(cb))
123        self.assertEqual(result, -18)
124
125    @need_symbol('c_longlong')
126    def test_longlong_callbacks(self):
127
128        f = dll._testfunc_callback_q_qf
129        f.restype = c_longlong
130
131        MyCallback = CFUNCTYPE(c_longlong, c_longlong)
132
133        f.argtypes = [c_longlong, MyCallback]
134
135        def callback(value):
136            self.assertIsInstance(value, int)
137            return value & 0x7FFFFFFF
138
139        cb = MyCallback(callback)
140
141        self.assertEqual(13577625587, int(f(self.wrap(1000000000000), self.wrap(cb))))
142
143    def test_byval(self):
144        # without prototype
145        ptin = POINT(1, 2)
146        ptout = POINT()
147        # EXPORT int _testfunc_byval(point in, point *pout)
148        result = dll._testfunc_byval(ptin, byref(ptout))
149        got = result, ptout.x, ptout.y
150        expected = 3, 1, 2
151        self.assertEqual(got, expected)
152
153        # with prototype
154        ptin = POINT(101, 102)
155        ptout = POINT()
156        dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
157        dll._testfunc_byval.restype = c_int
158        result = dll._testfunc_byval(self.wrap(ptin), byref(ptout))
159        got = result, ptout.x, ptout.y
160        expected = 203, 101, 102
161        self.assertEqual(got, expected)
162
163    def test_struct_return_2H(self):
164        class S2H(Structure):
165            _fields_ = [("x", c_short),
166                        ("y", c_short)]
167        dll.ret_2h_func.restype = S2H
168        dll.ret_2h_func.argtypes = [S2H]
169        inp = S2H(99, 88)
170        s2h = dll.ret_2h_func(self.wrap(inp))
171        self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
172
173        # Test also that the original struct was unmodified (i.e. was passed by
174        # value)
175        self.assertEqual((inp.x, inp.y), (99, 88))
176
177    def test_struct_return_8H(self):
178        class S8I(Structure):
179            _fields_ = [("a", c_int),
180                        ("b", c_int),
181                        ("c", c_int),
182                        ("d", c_int),
183                        ("e", c_int),
184                        ("f", c_int),
185                        ("g", c_int),
186                        ("h", c_int)]
187        dll.ret_8i_func.restype = S8I
188        dll.ret_8i_func.argtypes = [S8I]
189        inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
190        s8i = dll.ret_8i_func(self.wrap(inp))
191        self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
192                             (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
193
194    def test_recursive_as_param(self):
195        from ctypes import c_int
196
197        class A(object):
198            pass
199
200        a = A()
201        a._as_parameter_ = a
202        with self.assertRaises(RecursionError):
203            c_int.from_param(a)
204
205
206#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207
208class AsParamWrapper(object):
209    def __init__(self, param):
210        self._as_parameter_ = param
211
212class AsParamWrapperTestCase(BasicWrapTestCase):
213    wrap = AsParamWrapper
214
215#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216
217class AsParamPropertyWrapper(object):
218    def __init__(self, param):
219        self._param = param
220
221    def getParameter(self):
222        return self._param
223    _as_parameter_ = property(getParameter)
224
225class AsParamPropertyWrapperTestCase(BasicWrapTestCase):
226    wrap = AsParamPropertyWrapper
227
228#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229
230if __name__ == '__main__':
231    unittest.main()
232