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