1import unittest 2from test import support 3from ctypes import * 4 5import _ctypes_test 6 7lib = CDLL(_ctypes_test.__file__) 8 9class StringPtrTestCase(unittest.TestCase): 10 11 @support.refcount_test 12 def test__POINTER_c_char(self): 13 class X(Structure): 14 _fields_ = [("str", POINTER(c_char))] 15 x = X() 16 17 # NULL pointer access 18 self.assertRaises(ValueError, getattr, x.str, "contents") 19 b = c_buffer(b"Hello, World") 20 from sys import getrefcount as grc 21 self.assertEqual(grc(b), 2) 22 x.str = b 23 self.assertEqual(grc(b), 3) 24 25 # POINTER(c_char) and Python string is NOT compatible 26 # POINTER(c_char) and c_buffer() is compatible 27 for i in range(len(b)): 28 self.assertEqual(b[i], x.str[i]) 29 30 self.assertRaises(TypeError, setattr, x, "str", "Hello, World") 31 32 def test__c_char_p(self): 33 class X(Structure): 34 _fields_ = [("str", c_char_p)] 35 x = X() 36 37 # c_char_p and Python string is compatible 38 # c_char_p and c_buffer is NOT compatible 39 self.assertEqual(x.str, None) 40 x.str = b"Hello, World" 41 self.assertEqual(x.str, b"Hello, World") 42 b = c_buffer(b"Hello, World") 43 self.assertRaises(TypeError, setattr, x, b"str", b) 44 45 46 def test_functions(self): 47 strchr = lib.my_strchr 48 strchr.restype = c_char_p 49 50 # c_char_p and Python string is compatible 51 # c_char_p and c_buffer are now compatible 52 strchr.argtypes = c_char_p, c_char 53 self.assertEqual(strchr(b"abcdef", b"c"), b"cdef") 54 self.assertEqual(strchr(c_buffer(b"abcdef"), b"c"), b"cdef") 55 56 # POINTER(c_char) and Python string is NOT compatible 57 # POINTER(c_char) and c_buffer() is compatible 58 strchr.argtypes = POINTER(c_char), c_char 59 buf = c_buffer(b"abcdef") 60 self.assertEqual(strchr(buf, b"c"), b"cdef") 61 self.assertEqual(strchr(b"abcdef", b"c"), b"cdef") 62 63 # XXX These calls are dangerous, because the first argument 64 # to strchr is no longer valid after the function returns! 65 # So we must keep a reference to buf separately 66 67 strchr.restype = POINTER(c_char) 68 buf = c_buffer(b"abcdef") 69 r = strchr(buf, b"c") 70 x = r[0], r[1], r[2], r[3], r[4] 71 self.assertEqual(x, (b"c", b"d", b"e", b"f", b"\000")) 72 del buf 73 # Because r is a pointer to memory that is freed after deleting buf, 74 # the pointer is hanging and using it would reference freed memory. 75 76if __name__ == '__main__': 77 unittest.main() 78