• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import unittest
2from ctypes import *
3
4import _ctypes_test
5
6class ReturnFuncPtrTestCase(unittest.TestCase):
7
8    def test_with_prototype(self):
9        # The _ctypes_test shared lib/dll exports quite some functions for testing.
10        # The get_strchr function returns a *pointer* to the C strchr function.
11        dll = CDLL(_ctypes_test.__file__)
12        get_strchr = dll.get_strchr
13        get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char)
14        strchr = get_strchr()
15        self.assertEqual(strchr(b"abcdef", b"b"), b"bcdef")
16        self.assertEqual(strchr(b"abcdef", b"x"), None)
17        self.assertEqual(strchr(b"abcdef", 98), b"bcdef")
18        self.assertEqual(strchr(b"abcdef", 107), None)
19        self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)
20        self.assertRaises(TypeError, strchr, b"abcdef")
21
22    def test_without_prototype(self):
23        dll = CDLL(_ctypes_test.__file__)
24        get_strchr = dll.get_strchr
25        # the default 'c_int' would not work on systems where sizeof(int) != sizeof(void *)
26        get_strchr.restype = c_void_p
27        addr = get_strchr()
28        # _CFuncPtr instances are now callable with an integer argument
29        # which denotes a function address:
30        strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(addr)
31        self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")
32        self.assertEqual(strchr(b"abcdef", b"x"), None)
33        self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)
34        self.assertRaises(TypeError, strchr, b"abcdef")
35
36    def test_from_dll(self):
37        dll = CDLL(_ctypes_test.__file__)
38        # _CFuncPtr instances are now callable with a tuple argument
39        # which denotes a function name and a dll:
40        strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(("my_strchr", dll))
41        self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")
42        self.assertEqual(strchr(b"abcdef", b"x"), None)
43        self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)
44        self.assertRaises(TypeError, strchr, b"abcdef")
45
46    # Issue 6083: Reference counting bug
47    def test_from_dll_refcount(self):
48        class BadSequence(tuple):
49            def __getitem__(self, key):
50                if key == 0:
51                    return "my_strchr"
52                if key == 1:
53                    return CDLL(_ctypes_test.__file__)
54                raise IndexError
55
56        # _CFuncPtr instances are now callable with a tuple argument
57        # which denotes a function name and a dll:
58        strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(
59                BadSequence(("my_strchr", CDLL(_ctypes_test.__file__))))
60        self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")
61        self.assertEqual(strchr(b"abcdef", b"x"), None)
62        self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)
63        self.assertRaises(TypeError, strchr, b"abcdef")
64
65if __name__ == "__main__":
66    unittest.main()
67