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