summaryrefslogtreecommitdiff
path: root/lib/python2.7/ctypes/test/test_prototypes.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/ctypes/test/test_prototypes.py')
-rw-r--r--lib/python2.7/ctypes/test/test_prototypes.py221
1 files changed, 221 insertions, 0 deletions
diff --git a/lib/python2.7/ctypes/test/test_prototypes.py b/lib/python2.7/ctypes/test/test_prototypes.py
new file mode 100644
index 0000000..09ba655
--- /dev/null
+++ b/lib/python2.7/ctypes/test/test_prototypes.py
@@ -0,0 +1,221 @@
+from ctypes import *
+import unittest
+
+# IMPORTANT INFO:
+#
+# Consider this call:
+# func.restype = c_char_p
+# func(c_char_p("123"))
+# It returns
+# "123"
+#
+# WHY IS THIS SO?
+#
+# argument tuple (c_char_p("123"), ) is destroyed after the function
+# func is called, but NOT before the result is actually built.
+#
+# If the arglist would be destroyed BEFORE the result has been built,
+# the c_char_p("123") object would already have a zero refcount,
+# and the pointer passed to (and returned by) the function would
+# probably point to deallocated space.
+#
+# In this case, there would have to be an additional reference to the argument...
+
+import _ctypes_test
+testdll = CDLL(_ctypes_test.__file__)
+
+# Return machine address `a` as a (possibly long) non-negative integer.
+# Starting with Python 2.5, id(anything) is always non-negative, and
+# the ctypes addressof() inherits that via PyLong_FromVoidPtr().
+def positive_address(a):
+ if a >= 0:
+ return a
+ # View the bits in `a` as unsigned instead.
+ import struct
+ num_bits = struct.calcsize("P") * 8 # num bits in native machine address
+ a += 1L << num_bits
+ assert a >= 0
+ return a
+
+def c_wbuffer(init):
+ n = len(init) + 1
+ return (c_wchar * n)(*init)
+
+class CharPointersTestCase(unittest.TestCase):
+
+ def setUp(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_long
+ func.argtypes = None
+
+ def test_paramflags(self):
+ # function returns c_void_p result,
+ # and has a required parameter named 'input'
+ prototype = CFUNCTYPE(c_void_p, c_void_p)
+ func = prototype(("_testfunc_p_p", testdll),
+ ((1, "input"),))
+
+ try:
+ func()
+ except TypeError, details:
+ self.assertEqual(str(details), "required argument 'input' missing")
+ else:
+ self.fail("TypeError not raised")
+
+ self.assertEqual(func(None), None)
+ self.assertEqual(func(input=None), None)
+
+
+ def test_int_pointer_arg(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_long
+ self.assertEqual(0, func(0))
+
+ ci = c_int(0)
+
+ func.argtypes = POINTER(c_int),
+ self.assertEqual(positive_address(addressof(ci)),
+ positive_address(func(byref(ci))))
+
+ func.argtypes = c_char_p,
+ self.assertRaises(ArgumentError, func, byref(ci))
+
+ func.argtypes = POINTER(c_short),
+ self.assertRaises(ArgumentError, func, byref(ci))
+
+ func.argtypes = POINTER(c_double),
+ self.assertRaises(ArgumentError, func, byref(ci))
+
+ def test_POINTER_c_char_arg(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_char_p
+ func.argtypes = POINTER(c_char),
+
+ self.assertEqual(None, func(None))
+ self.assertEqual("123", func("123"))
+ self.assertEqual(None, func(c_char_p(None)))
+ self.assertEqual("123", func(c_char_p("123")))
+
+ self.assertEqual("123", func(c_buffer("123")))
+ ca = c_char("a")
+ self.assertEqual("a", func(pointer(ca))[0])
+ self.assertEqual("a", func(byref(ca))[0])
+
+ def test_c_char_p_arg(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_char_p
+ func.argtypes = c_char_p,
+
+ self.assertEqual(None, func(None))
+ self.assertEqual("123", func("123"))
+ self.assertEqual(None, func(c_char_p(None)))
+ self.assertEqual("123", func(c_char_p("123")))
+
+ self.assertEqual("123", func(c_buffer("123")))
+ ca = c_char("a")
+ self.assertEqual("a", func(pointer(ca))[0])
+ self.assertEqual("a", func(byref(ca))[0])
+
+ def test_c_void_p_arg(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_char_p
+ func.argtypes = c_void_p,
+
+ self.assertEqual(None, func(None))
+ self.assertEqual("123", func("123"))
+ self.assertEqual("123", func(c_char_p("123")))
+ self.assertEqual(None, func(c_char_p(None)))
+
+ self.assertEqual("123", func(c_buffer("123")))
+ ca = c_char("a")
+ self.assertEqual("a", func(pointer(ca))[0])
+ self.assertEqual("a", func(byref(ca))[0])
+
+ func(byref(c_int()))
+ func(pointer(c_int()))
+ func((c_int * 3)())
+
+ try:
+ func.restype = c_wchar_p
+ except NameError:
+ pass
+ else:
+ self.assertEqual(None, func(c_wchar_p(None)))
+ self.assertEqual(u"123", func(c_wchar_p(u"123")))
+
+ def test_instance(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_void_p
+
+ class X:
+ _as_parameter_ = None
+
+ func.argtypes = c_void_p,
+ self.assertEqual(None, func(X()))
+
+ func.argtypes = None
+ self.assertEqual(None, func(X()))
+
+try:
+ c_wchar
+except NameError:
+ pass
+else:
+ class WCharPointersTestCase(unittest.TestCase):
+
+ def setUp(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_int
+ func.argtypes = None
+
+
+ def test_POINTER_c_wchar_arg(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_wchar_p
+ func.argtypes = POINTER(c_wchar),
+
+ self.assertEqual(None, func(None))
+ self.assertEqual(u"123", func(u"123"))
+ self.assertEqual(None, func(c_wchar_p(None)))
+ self.assertEqual(u"123", func(c_wchar_p(u"123")))
+
+ self.assertEqual(u"123", func(c_wbuffer(u"123")))
+ ca = c_wchar("a")
+ self.assertEqual(u"a", func(pointer(ca))[0])
+ self.assertEqual(u"a", func(byref(ca))[0])
+
+ def test_c_wchar_p_arg(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_wchar_p
+ func.argtypes = c_wchar_p,
+
+ c_wchar_p.from_param(u"123")
+
+ self.assertEqual(None, func(None))
+ self.assertEqual("123", func(u"123"))
+ self.assertEqual(None, func(c_wchar_p(None)))
+ self.assertEqual("123", func(c_wchar_p("123")))
+
+ # XXX Currently, these raise TypeErrors, although they shouldn't:
+ self.assertEqual("123", func(c_wbuffer("123")))
+ ca = c_wchar("a")
+ self.assertEqual("a", func(pointer(ca))[0])
+ self.assertEqual("a", func(byref(ca))[0])
+
+class ArrayTest(unittest.TestCase):
+ def test(self):
+ func = testdll._testfunc_ai8
+ func.restype = POINTER(c_int)
+ func.argtypes = c_int * 8,
+
+ func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8))
+
+ # This did crash before:
+
+ def func(): pass
+ CFUNCTYPE(None, c_int * 3)(func)
+
+################################################################
+
+if __name__ == '__main__':
+ unittest.main()