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