PageRenderTime 445ms CodeModel.GetById 141ms app.highlight 81ms RepoModel.GetById 220ms app.codeStats 0ms

/Lib/ctypes/test/test_prototypes.py

http://unladen-swallow.googlecode.com/
Python | 221 lines | 146 code | 47 blank | 28 comment | 2 complexity | 42652a9e5466dc7208b096e86da1953e MD5 | raw file
  1from ctypes import *
  2import unittest
  3
  4# IMPORTANT INFO:
  5#
  6# Consider this call:
  7#    func.restype = c_char_p
  8#    func(c_char_p("123"))
  9# It returns
 10#    "123"
 11#
 12# WHY IS THIS SO?
 13#
 14# argument tuple (c_char_p("123"), ) is destroyed after the function
 15# func is called, but NOT before the result is actually built.
 16#
 17# If the arglist would be destroyed BEFORE the result has been built,
 18# the c_char_p("123") object would already have a zero refcount,
 19# and the pointer passed to (and returned by) the function would
 20# probably point to deallocated space.
 21#
 22# In this case, there would have to be an additional reference to the argument...
 23
 24import _ctypes_test
 25testdll = CDLL(_ctypes_test.__file__)
 26
 27# Return machine address `a` as a (possibly long) non-negative integer.
 28# Starting with Python 2.5, id(anything) is always non-negative, and
 29# the ctypes addressof() inherits that via PyLong_FromVoidPtr().
 30def positive_address(a):
 31    if a >= 0:
 32        return a
 33    # View the bits in `a` as unsigned instead.
 34    import struct
 35    num_bits = struct.calcsize("P") * 8 # num bits in native machine address
 36    a += 1L << num_bits
 37    assert a >= 0
 38    return a
 39
 40def c_wbuffer(init):
 41    n = len(init) + 1
 42    return (c_wchar * n)(*init)
 43
 44class CharPointersTestCase(unittest.TestCase):
 45
 46    def setUp(self):
 47        func = testdll._testfunc_p_p
 48        func.restype = c_long
 49        func.argtypes = None
 50
 51    def test_paramflags(self):
 52        # function returns c_void_p result,
 53        # and has a required parameter named 'input'
 54        prototype = CFUNCTYPE(c_void_p, c_void_p)
 55        func = prototype(("_testfunc_p_p", testdll),
 56                         ((1, "input"),))
 57
 58        try:
 59            func()
 60        except TypeError, details:
 61            self.failUnlessEqual(str(details), "required argument 'input' missing")
 62        else:
 63            self.fail("TypeError not raised")
 64
 65        self.failUnlessEqual(func(None), None)
 66        self.failUnlessEqual(func(input=None), None)
 67
 68
 69    def test_int_pointer_arg(self):
 70        func = testdll._testfunc_p_p
 71        func.restype = c_long
 72        self.failUnlessEqual(0, func(0))
 73
 74        ci = c_int(0)
 75
 76        func.argtypes = POINTER(c_int),
 77        self.failUnlessEqual(positive_address(addressof(ci)),
 78                             positive_address(func(byref(ci))))
 79
 80        func.argtypes = c_char_p,
 81        self.assertRaises(ArgumentError, func, byref(ci))
 82
 83        func.argtypes = POINTER(c_short),
 84        self.assertRaises(ArgumentError, func, byref(ci))
 85
 86        func.argtypes = POINTER(c_double),
 87        self.assertRaises(ArgumentError, func, byref(ci))
 88
 89    def test_POINTER_c_char_arg(self):
 90        func = testdll._testfunc_p_p
 91        func.restype = c_char_p
 92        func.argtypes = POINTER(c_char),
 93
 94        self.failUnlessEqual(None, func(None))
 95        self.failUnlessEqual("123", func("123"))
 96        self.failUnlessEqual(None, func(c_char_p(None)))
 97        self.failUnlessEqual("123", func(c_char_p("123")))
 98
 99        self.failUnlessEqual("123", func(c_buffer("123")))
100        ca = c_char("a")
101        self.failUnlessEqual("a", func(pointer(ca))[0])
102        self.failUnlessEqual("a", func(byref(ca))[0])
103
104    def test_c_char_p_arg(self):
105        func = testdll._testfunc_p_p
106        func.restype = c_char_p
107        func.argtypes = c_char_p,
108
109        self.failUnlessEqual(None, func(None))
110        self.failUnlessEqual("123", func("123"))
111        self.failUnlessEqual(None, func(c_char_p(None)))
112        self.failUnlessEqual("123", func(c_char_p("123")))
113
114        self.failUnlessEqual("123", func(c_buffer("123")))
115        ca = c_char("a")
116        self.failUnlessEqual("a", func(pointer(ca))[0])
117        self.failUnlessEqual("a", func(byref(ca))[0])
118
119    def test_c_void_p_arg(self):
120        func = testdll._testfunc_p_p
121        func.restype = c_char_p
122        func.argtypes = c_void_p,
123
124        self.failUnlessEqual(None, func(None))
125        self.failUnlessEqual("123", func("123"))
126        self.failUnlessEqual("123", func(c_char_p("123")))
127        self.failUnlessEqual(None, func(c_char_p(None)))
128
129        self.failUnlessEqual("123", func(c_buffer("123")))
130        ca = c_char("a")
131        self.failUnlessEqual("a", func(pointer(ca))[0])
132        self.failUnlessEqual("a", func(byref(ca))[0])
133
134        func(byref(c_int()))
135        func(pointer(c_int()))
136        func((c_int * 3)())
137
138        try:
139            func.restype = c_wchar_p
140        except NameError:
141            pass
142        else:
143            self.failUnlessEqual(None, func(c_wchar_p(None)))
144            self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
145
146    def test_instance(self):
147        func = testdll._testfunc_p_p
148        func.restype = c_void_p
149
150        class X:
151            _as_parameter_ = None
152
153        func.argtypes = c_void_p,
154        self.failUnlessEqual(None, func(X()))
155
156        func.argtypes = None
157        self.failUnlessEqual(None, func(X()))
158
159try:
160    c_wchar
161except NameError:
162    pass
163else:
164    class WCharPointersTestCase(unittest.TestCase):
165
166        def setUp(self):
167            func = testdll._testfunc_p_p
168            func.restype = c_int
169            func.argtypes = None
170
171
172        def test_POINTER_c_wchar_arg(self):
173            func = testdll._testfunc_p_p
174            func.restype = c_wchar_p
175            func.argtypes = POINTER(c_wchar),
176
177            self.failUnlessEqual(None, func(None))
178            self.failUnlessEqual(u"123", func(u"123"))
179            self.failUnlessEqual(None, func(c_wchar_p(None)))
180            self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
181
182            self.failUnlessEqual(u"123", func(c_wbuffer(u"123")))
183            ca = c_wchar("a")
184            self.failUnlessEqual(u"a", func(pointer(ca))[0])
185            self.failUnlessEqual(u"a", func(byref(ca))[0])
186
187        def test_c_wchar_p_arg(self):
188            func = testdll._testfunc_p_p
189            func.restype = c_wchar_p
190            func.argtypes = c_wchar_p,
191
192            c_wchar_p.from_param(u"123")
193
194            self.failUnlessEqual(None, func(None))
195            self.failUnlessEqual("123", func(u"123"))
196            self.failUnlessEqual(None, func(c_wchar_p(None)))
197            self.failUnlessEqual("123", func(c_wchar_p("123")))
198
199            # XXX Currently, these raise TypeErrors, although they shouldn't:
200            self.failUnlessEqual("123", func(c_wbuffer("123")))
201            ca = c_wchar("a")
202            self.failUnlessEqual("a", func(pointer(ca))[0])
203            self.failUnlessEqual("a", func(byref(ca))[0])
204
205class ArrayTest(unittest.TestCase):
206    def test(self):
207        func = testdll._testfunc_ai8
208        func.restype = POINTER(c_int)
209        func.argtypes = c_int * 8,
210
211        func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8))
212
213        # This did crash before:
214
215        def func(): pass
216        CFUNCTYPE(None, c_int * 3)(func)
217
218################################################################
219
220if __name__ == '__main__':
221    unittest.main()