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