1import unittest 2from ctypes import * 3import re, sys 4 5if sys.byteorder == "little": 6 THIS_ENDIAN = "<" 7 OTHER_ENDIAN = ">" 8else: 9 THIS_ENDIAN = ">" 10 OTHER_ENDIAN = "<" 11 12def normalize(format): 13 # Remove current endian specifier and white space from a format 14 # string 15 if format is None: 16 return "" 17 format = format.replace(OTHER_ENDIAN, THIS_ENDIAN) 18 return re.sub(r"\s", "", format) 19 20class Test(unittest.TestCase): 21 22 def test_native_types(self): 23 for tp, fmt, shape, itemtp in native_types: 24 ob = tp() 25 v = memoryview(ob) 26 try: 27 self.assertEqual(normalize(v.format), normalize(fmt)) 28 if shape: 29 self.assertEqual(len(v), shape[0]) 30 else: 31 self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) 32 self.assertEqual(v.itemsize, sizeof(itemtp)) 33 self.assertEqual(v.shape, shape) 34 # XXX Issue #12851: PyCData_NewGetBuffer() must provide strides 35 # if requested. memoryview currently reconstructs missing 36 # stride information, so this assert will fail. 37 # self.assertEqual(v.strides, ()) 38 39 # they are always read/write 40 self.assertFalse(v.readonly) 41 42 if v.shape: 43 n = 1 44 for dim in v.shape: 45 n = n * dim 46 self.assertEqual(n * v.itemsize, len(v.tobytes())) 47 except: 48 # so that we can see the failing type 49 print(tp) 50 raise 51 52 def test_endian_types(self): 53 for tp, fmt, shape, itemtp in endian_types: 54 ob = tp() 55 v = memoryview(ob) 56 try: 57 self.assertEqual(v.format, fmt) 58 if shape: 59 self.assertEqual(len(v), shape[0]) 60 else: 61 self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) 62 self.assertEqual(v.itemsize, sizeof(itemtp)) 63 self.assertEqual(v.shape, shape) 64 # XXX Issue #12851 65 # self.assertEqual(v.strides, ()) 66 67 # they are always read/write 68 self.assertFalse(v.readonly) 69 70 if v.shape: 71 n = 1 72 for dim in v.shape: 73 n = n * dim 74 self.assertEqual(n, len(v)) 75 except: 76 # so that we can see the failing type 77 print(tp) 78 raise 79 80# define some structure classes 81 82class Point(Structure): 83 _fields_ = [("x", c_long), ("y", c_long)] 84 85class PackedPoint(Structure): 86 _pack_ = 2 87 _fields_ = [("x", c_long), ("y", c_long)] 88 89class Point2(Structure): 90 pass 91Point2._fields_ = [("x", c_long), ("y", c_long)] 92 93class EmptyStruct(Structure): 94 _fields_ = [] 95 96class aUnion(Union): 97 _fields_ = [("a", c_int)] 98 99class StructWithArrays(Structure): 100 _fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)] 101 102class Incomplete(Structure): 103 pass 104 105class Complete(Structure): 106 pass 107PComplete = POINTER(Complete) 108Complete._fields_ = [("a", c_long)] 109 110################################################################ 111# 112# This table contains format strings as they look on little endian 113# machines. The test replaces '<' with '>' on big endian machines. 114# 115 116# Platform-specific type codes 117s_bool = {1: '?', 2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_bool)] 118s_short = {2: 'h', 4: 'l', 8: 'q'}[sizeof(c_short)] 119s_ushort = {2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_ushort)] 120s_int = {2: 'h', 4: 'i', 8: 'q'}[sizeof(c_int)] 121s_uint = {2: 'H', 4: 'I', 8: 'Q'}[sizeof(c_uint)] 122s_long = {4: 'l', 8: 'q'}[sizeof(c_long)] 123s_ulong = {4: 'L', 8: 'Q'}[sizeof(c_ulong)] 124s_longlong = "q" 125s_ulonglong = "Q" 126s_float = "f" 127s_double = "d" 128s_longdouble = "g" 129 130# Alias definitions in ctypes/__init__.py 131if c_int is c_long: 132 s_int = s_long 133if c_uint is c_ulong: 134 s_uint = s_ulong 135if c_longlong is c_long: 136 s_longlong = s_long 137if c_ulonglong is c_ulong: 138 s_ulonglong = s_ulong 139if c_longdouble is c_double: 140 s_longdouble = s_double 141 142 143native_types = [ 144 # type format shape calc itemsize 145 146 ## simple types 147 148 (c_char, "<c", (), c_char), 149 (c_byte, "<b", (), c_byte), 150 (c_ubyte, "<B", (), c_ubyte), 151 (c_short, "<" + s_short, (), c_short), 152 (c_ushort, "<" + s_ushort, (), c_ushort), 153 154 (c_int, "<" + s_int, (), c_int), 155 (c_uint, "<" + s_uint, (), c_uint), 156 157 (c_long, "<" + s_long, (), c_long), 158 (c_ulong, "<" + s_ulong, (), c_ulong), 159 160 (c_longlong, "<" + s_longlong, (), c_longlong), 161 (c_ulonglong, "<" + s_ulonglong, (), c_ulonglong), 162 163 (c_float, "<f", (), c_float), 164 (c_double, "<d", (), c_double), 165 166 (c_longdouble, "<" + s_longdouble, (), c_longdouble), 167 168 (c_bool, "<" + s_bool, (), c_bool), 169 (py_object, "<O", (), py_object), 170 171 ## pointers 172 173 (POINTER(c_byte), "&<b", (), POINTER(c_byte)), 174 (POINTER(POINTER(c_long)), "&&<" + s_long, (), POINTER(POINTER(c_long))), 175 176 ## arrays and pointers 177 178 (c_double * 4, "<d", (4,), c_double), 179 (c_float * 4 * 3 * 2, "<f", (2,3,4), c_float), 180 (POINTER(c_short) * 2, "&<" + s_short, (2,), POINTER(c_short)), 181 (POINTER(c_short) * 2 * 3, "&<" + s_short, (3,2,), POINTER(c_short)), 182 (POINTER(c_short * 2), "&(2)<" + s_short, (), POINTER(c_short)), 183 184 ## structures and unions 185 186 (Point, "T{<l:x:<l:y:}".replace('l', s_long), (), Point), 187 # packed structures do not implement the pep 188 (PackedPoint, "B", (), PackedPoint), 189 (Point2, "T{<l:x:<l:y:}".replace('l', s_long), (), Point2), 190 (EmptyStruct, "T{}", (), EmptyStruct), 191 # the pep doesn't support unions 192 (aUnion, "B", (), aUnion), 193 # structure with sub-arrays 194 (StructWithArrays, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), (), StructWithArrays), 195 (StructWithArrays * 3, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), (3,), StructWithArrays), 196 197 ## pointer to incomplete structure 198 (Incomplete, "B", (), Incomplete), 199 (POINTER(Incomplete), "&B", (), POINTER(Incomplete)), 200 201 # 'Complete' is a structure that starts incomplete, but is completed after the 202 # pointer type to it has been created. 203 (Complete, "T{<l:a:}".replace('l', s_long), (), Complete), 204 # Unfortunately the pointer format string is not fixed... 205 (POINTER(Complete), "&B", (), POINTER(Complete)), 206 207 ## other 208 209 # function signatures are not implemented 210 (CFUNCTYPE(None), "X{}", (), CFUNCTYPE(None)), 211 212 ] 213 214class BEPoint(BigEndianStructure): 215 _fields_ = [("x", c_long), ("y", c_long)] 216 217class LEPoint(LittleEndianStructure): 218 _fields_ = [("x", c_long), ("y", c_long)] 219 220################################################################ 221# 222# This table contains format strings as they really look, on both big 223# and little endian machines. 224# 225endian_types = [ 226 (BEPoint, "T{>l:x:>l:y:}".replace('l', s_long), (), BEPoint), 227 (LEPoint, "T{<l:x:<l:y:}".replace('l', s_long), (), LEPoint), 228 (POINTER(BEPoint), "&T{>l:x:>l:y:}".replace('l', s_long), (), POINTER(BEPoint)), 229 (POINTER(LEPoint), "&T{<l:x:<l:y:}".replace('l', s_long), (), POINTER(LEPoint)), 230 ] 231 232if __name__ == "__main__": 233 unittest.main() 234