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