Home | History | Annotate | Download | only in test
      1 import unittest
      2 from ctypes import *
      3 from ctypes.test import need_symbol
      4 import _ctypes_test
      5 
      6 dll = CDLL(_ctypes_test.__file__)
      7 
      8 try:
      9     CALLBACK_FUNCTYPE = WINFUNCTYPE
     10 except NameError:
     11     # fake to enable this test on Linux
     12     CALLBACK_FUNCTYPE = CFUNCTYPE
     13 
     14 class POINT(Structure):
     15     _fields_ = [("x", c_int), ("y", c_int)]
     16 
     17 class 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(u"x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0))
     26         self.assertEqual(result, 139)
     27         self.assertTrue(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     def test_longlong_callbacks(self):
    126 
    127         f = dll._testfunc_callback_q_qf
    128         f.restype = c_longlong
    129 
    130         MyCallback = CFUNCTYPE(c_longlong, c_longlong)
    131 
    132         f.argtypes = [c_longlong, MyCallback]
    133 
    134         def callback(value):
    135             self.assertIsInstance(value, (int, long))
    136             return value & 0x7FFFFFFF
    137 
    138         cb = MyCallback(callback)
    139 
    140         self.assertEqual(13577625587, int(f(self.wrap(1000000000000), self.wrap(cb))))
    141 
    142     def test_byval(self):
    143         # without prototype
    144         ptin = POINT(1, 2)
    145         ptout = POINT()
    146         # EXPORT int _testfunc_byval(point in, point *pout)
    147         result = dll._testfunc_byval(ptin, byref(ptout))
    148         got = result, ptout.x, ptout.y
    149         expected = 3, 1, 2
    150         self.assertEqual(got, expected)
    151 
    152         # with prototype
    153         ptin = POINT(101, 102)
    154         ptout = POINT()
    155         dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
    156         dll._testfunc_byval.restype = c_int
    157         result = dll._testfunc_byval(self.wrap(ptin), byref(ptout))
    158         got = result, ptout.x, ptout.y
    159         expected = 203, 101, 102
    160         self.assertEqual(got, expected)
    161 
    162     def test_struct_return_2H(self):
    163         class S2H(Structure):
    164             _fields_ = [("x", c_short),
    165                         ("y", c_short)]
    166         dll.ret_2h_func.restype = S2H
    167         dll.ret_2h_func.argtypes = [S2H]
    168         inp = S2H(99, 88)
    169         s2h = dll.ret_2h_func(self.wrap(inp))
    170         self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
    171 
    172     def test_struct_return_8H(self):
    173         class S8I(Structure):
    174             _fields_ = [("a", c_int),
    175                         ("b", c_int),
    176                         ("c", c_int),
    177                         ("d", c_int),
    178                         ("e", c_int),
    179                         ("f", c_int),
    180                         ("g", c_int),
    181                         ("h", c_int)]
    182         dll.ret_8i_func.restype = S8I
    183         dll.ret_8i_func.argtypes = [S8I]
    184         inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
    185         s8i = dll.ret_8i_func(self.wrap(inp))
    186         self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
    187                              (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
    188 
    189     def test_recursive_as_param(self):
    190         from ctypes import c_int
    191 
    192         class A(object):
    193             pass
    194 
    195         a = A()
    196         a._as_parameter_ = a
    197         with self.assertRaises(RuntimeError):
    198             c_int.from_param(a)
    199 
    200 
    201 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    202 
    203 class AsParamWrapper(object):
    204     def __init__(self, param):
    205         self._as_parameter_ = param
    206 
    207 class AsParamWrapperTestCase(BasicWrapTestCase):
    208     wrap = AsParamWrapper
    209 
    210 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    211 
    212 class AsParamPropertyWrapper(object):
    213     def __init__(self, param):
    214         self._param = param
    215 
    216     def getParameter(self):
    217         return self._param
    218     _as_parameter_ = property(getParameter)
    219 
    220 class AsParamPropertyWrapperTestCase(BasicWrapTestCase):
    221     wrap = AsParamPropertyWrapper
    222 
    223 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    224 
    225 if __name__ == '__main__':
    226     unittest.main()
    227