def test_dirent(): dirent = configure.getstruct( "struct dirent", """ struct dirent /* for this example only, not the exact dirent */ { long d_ino; int d_off; unsigned short d_reclen; char d_name[32]; }; """, [("d_reclen", ctypes.c_ushort)]) assert issubclass(dirent, ctypes.Structure) ssize = (ctypes.sizeof(ctypes.c_long) + ctypes.sizeof(ctypes.c_int) + ctypes.sizeof(ctypes.c_ushort) + 32) extra_padding = (-ssize) % ctypes.alignment(ctypes.c_long) assert dirent._fields_ == [ ('_alignment', ctypes.c_long), ('_pad0', ctypes.c_char), ('_pad1', ctypes.c_char), ('_pad2', ctypes.c_char), ('_pad3', ctypes.c_char), ('d_reclen', ctypes.c_ushort), ] + [('_pad%d' % n, ctypes.c_char) for n in range(4, 4 + 32 + extra_padding)] assert ctypes.sizeof(dirent) == ssize + extra_padding assert ctypes.alignment(dirent) == ctypes.alignment(ctypes.c_long)
def test_dirent(): dirent = configure.getstruct("struct dirent", """ struct dirent /* for this example only, not the exact dirent */ { long d_ino; int d_off; unsigned short d_reclen; char d_name[32]; }; """, [("d_reclen", ctypes.c_ushort)]) assert issubclass(dirent, ctypes.Structure) ssize = (ctypes.sizeof(ctypes.c_long) + ctypes.sizeof(ctypes.c_int) + ctypes.sizeof(ctypes.c_ushort) + 32) extra_padding = (-ssize) % ctypes.alignment(ctypes.c_long) assert dirent._fields_ == [('_alignment', ctypes.c_long), ('_pad0', ctypes.c_char), ('_pad1', ctypes.c_char), ('_pad2', ctypes.c_char), ('_pad3', ctypes.c_char), ('d_reclen', ctypes.c_ushort), ] + [ ('_pad%d' % n, ctypes.c_char) for n in range(4, 4+32+extra_padding)] assert ctypes.sizeof(dirent) == ssize + extra_padding assert ctypes.alignment(dirent) == ctypes.alignment(ctypes.c_long)
def checkUnalignedPtrs(t): if not hasattr(t, "_fields_"): return # no fields = no alignment problems if hasattr(t, "allow_unaligned"): allowed = t.allow_unaligned else: allowed = [] for fieldinfo in t._fields_: # note this tuple may have 3 values for a bitfield fname, ftype = fieldinfo[0], fieldinfo[1] alignment = ctypes.alignment(ftype) if alignment == 0: continue field = getattr(t, fname) if field.offset % alignment == 0: # This field is a aligned continue if not hasPointers(ftype): # We'll allow unaligned things that aren't pointers continue # misaligned field that is a/has pointers. This trips up valgrind. if fname not in allowed: addError( "unaligned ptr field %s in %s: offset=%d [%d]" % (fname, t.__name__, field.offset, field.offset % alignment))
def find_out_offset_of_tp_name_in_PyTypeObject(max=128): step = alignment(c_void_p) #print(step, sizeof(c_void_p)) name = '_00_01_' T = type(name, (), {}) addr = pyobj2pyaddr(T) # a type object not instance!! name = name.encode('utf-8') null_ptr = POINTER(c_char_p)() assert not null_ptr assert null_ptr != POINTER(c_char_p)() # why !!!!!!!!!!!!! #no contents: assert null_ptr.contents != POINTER(c_char_p)().contents for offset in range(0, max + 1, step): addr_of_ty_name_addr = addr + offset ty_name_addr = addrofaddr2addr(addr_of_ty_name_addr) if ty_name_addr is None: continue try: ty_name = string_at(ty_name_addr, 1) # assert type(ty_name) is bytes #print(ty_name, name) if name.startswith(ty_name): ty_name = string_at(ty_name_addr, len(name)) if name == ty_name: break except OSError: continue else: raise logic - error return offset
def _from_ctypes_structure(t): for item in t._fields_: if len(item) > 2: raise TypeError("ctypes bitfields have no dtype equivalent") if hasattr(t, "_pack_"): formats = [] offsets = [] names = [] current_offset = 0 for fname, ftyp in t._fields_: names.append(fname) formats.append(dtype_from_ctypes_type(ftyp)) # Each type has a default offset, this is platform dependent for some types. effective_pack = min(t._pack_, ctypes.alignment(ftyp)) current_offset = ((current_offset + effective_pack - 1) // effective_pack) * effective_pack offsets.append(current_offset) current_offset += ctypes.sizeof(ftyp) return np.dtype( dict(formats=formats, offsets=offsets, names=names, itemsize=ctypes.sizeof(t))) else: fields = [] for fname, ftyp in t._fields_: fields.append((fname, dtype_from_ctypes_type(ftyp))) # by default, ctypes structs are aligned return np.dtype(fields, align=True)
def ctype_alignment(c_type): if issubclass(c_type, ctypes.Structure): return max([ ctype_alignment(fld_type) for fld_name, fld_type in c_type._fields_ ]) return ctypes.alignment(c_type)
def test_time_type_properties(self): self.assertEqual(type(ndt.time), ndt.type) self.assertEqual(str(ndt.time), 'time') self.assertEqual(ndt.time.data_size, 8) self.assertEqual(ndt.time.data_alignment, ctypes.alignment(ctypes.c_int64)) self.assertEqual(ndt.time.canonical_type, ndt.time)
def _from_ctypes_structure(t): for item in t._fields_: if len(item) > 2: raise TypeError( "ctypes bitfields have no dtype equivalent") if hasattr(t, "_pack_"): formats = [] offsets = [] names = [] current_offset = 0 for fname, ftyp in t._fields_: names.append(fname) formats.append(dtype_from_ctypes_type(ftyp)) # Each type has a default offset, this is platform dependent for some types. effective_pack = min(t._pack_, ctypes.alignment(ftyp)) current_offset = ((current_offset + effective_pack - 1) // effective_pack) * effective_pack offsets.append(current_offset) current_offset += ctypes.sizeof(ftyp) return np.dtype(dict( formats=formats, offsets=offsets, names=names, itemsize=ctypes.sizeof(t))) else: fields = [] for fname, ftyp in t._fields_: fields.append((fname, dtype_from_ctypes_type(ftyp))) # by default, ctypes structs are aligned return np.dtype(fields, align=True)
def _alignmentofinstances(self): from ctypes import alignment if not hasattr(self, '_alignment_'): self._alignment_ = max([ alignment(field.ctype) for field in self._fieldtypes.values() ] + [1]) return self._alignment_
def bcm_header_factory(fields, alignment=8): curr_stride = 0 results = [] pad_index = 0 for field in fields: field_alignment = ctypes.alignment(field[1]) field_size = ctypes.sizeof(field[1]) # If the current stride index isn't a multiple of the alignment # requirements of this field, then we must add padding bytes until we # are aligned while curr_stride % field_alignment != 0: results.append(("pad_{}".format(pad_index), ctypes.c_uint8)) pad_index += 1 curr_stride += 1 # Now can it fit? # Example: If this is 8 bytes and the type requires 4 bytes alignment # then we can only fit when we're starting at 0. Otherwise, we will # split across 2 strides. # # | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | results.append(field) curr_stride += field_size # Add trailing padding to align to a multiple of the largest scalar member # in the structure while curr_stride % alignment != 0: results.append(("pad_{}".format(pad_index), ctypes.c_uint8)) pad_index += 1 curr_stride += 1 return type("BcmMsgHead", (ctypes.Structure, ), {"_fields_": results})
def add_ivar(cls, name, vartype): "Add a new instance variable of type vartype to cls." return libobjc.class_addIvar( cls, ensure_bytes(name), sizeof(vartype), alignment(vartype), encoding_for_ctype(ctype_for_type(vartype)), )
def test_string(self): class StringData(ctypes.Structure): _fields_ = [('begin', ctypes.c_void_p), ('end', ctypes.c_void_p)] # string self.assertEqual(datashape.string.c_itemsize, ctypes.sizeof(StringData)) self.assertEqual(datashape.string.c_alignment, ctypes.alignment(StringData)) # bytes self.assertEqual(datashape.bytes_.c_itemsize, ctypes.sizeof(StringData)) self.assertEqual(datashape.bytes_.c_alignment, ctypes.alignment(StringData)) # json self.assertEqual(datashape.json.c_itemsize, ctypes.sizeof(StringData)) self.assertEqual(datashape.json.c_alignment, ctypes.alignment(StringData))
def test_record(self): class ctds(ctypes.Structure): _fields_ = [('a', ctypes.c_int8), ('b', ctypes.c_double), ('c', ctypes.c_uint8), ('d', ctypes.c_uint16)] ds = datashape.dshape('{a: int8; b: float64; c: uint8; d: float16}') self.assertEqual(ds.c_itemsize, ctypes.sizeof(ctds)) self.assertEqual(ds.c_alignment, ctypes.alignment(ctds)) self.assertEqual(ds.c_offsets, (ctds.a.offset, ctds.b.offset, ctds.c.offset, ctds.d.offset))
def test_ctypes_alignment(self): self.assertEqual(datashape.int8.c_alignment, ctypes.alignment(ctypes.c_int8)) self.assertEqual(datashape.int16.c_alignment, ctypes.alignment(ctypes.c_int16)) self.assertEqual(datashape.int32.c_alignment, ctypes.alignment(ctypes.c_int32)) self.assertEqual(datashape.int64.c_alignment, ctypes.alignment(ctypes.c_int64)) self.assertEqual(datashape.uint8.c_alignment, ctypes.alignment(ctypes.c_uint8)) self.assertEqual(datashape.uint16.c_alignment, ctypes.alignment(ctypes.c_uint16)) self.assertEqual(datashape.uint32.c_alignment, ctypes.alignment(ctypes.c_uint32)) self.assertEqual(datashape.uint64.c_alignment, ctypes.alignment(ctypes.c_uint64)) self.assertEqual(datashape.float32.c_alignment, ctypes.alignment(ctypes.c_float)) self.assertEqual(datashape.float64.c_alignment, ctypes.alignment(ctypes.c_double))
def alloc(self, var_type): # Treat these as pointers for stack storage purposes if issubclass(var_type, _datastructures.FileDescriptorDatastructure): var_type = ctypes.c_voidp # Round up to nearest multiple of alignment. This works # because alignment is always a power of 2 al = ctypes.alignment(var_type) self.neg_stack_off += ctypes.sizeof(var_type) self.neg_stack_off += (al - 1) self.neg_stack_off &= ~(al - 1) return StackVar(var_type, -self.neg_stack_off)
def size_alignment_pos(fields): import ctypes size = 0 alignment = 1 pos = [] for fieldname, ctype in fields: fieldsize = ctypes.sizeof(ctype) fieldalignment = ctypes.alignment(ctype) size = round_up(size, fieldalignment) alignment = max(alignment, fieldalignment) pos.append(size) size += fieldsize size = round_up(size, alignment) return size, alignment, pos
def testTypes(): modelpath = "data\\model.xml" f = open(modelpath) model = xml.parse(f).getElementsByTagName("dll")[0] f.close() tc = typemanager.TypeManager(model) # Write it to a pickle file path = "junk\\test.pkl" f = open(path, "wb") pickle.dump(tc, f) f.close() # Read it back in path = "junk\\test.pkl" f = open(path, "rb") newtc = pickle.load(f) f.close() myclass = newtc.getClass("2") print ctypes.alignment(myclass) print ctypes.sizeof(myclass) print myclass._fields_ myinst = myclass('A', 0x7, 0x0, 'B') print getattr(myinst, "field-0")
def memory_alignment(): """Return the alignment (in bytes) of memory allocations. This is enough to make sure a structure with pointers and 'double' fields is properly aligned.""" global _memory_alignment if _memory_alignment is None: S = getstruct('struct memory_alignment_test', """ struct memory_alignment_test { double d; void* p; }; """, []) result = ctypes.alignment(S) assert result & (result-1) == 0, "not a power of two??" _memory_alignment = result return _memory_alignment
def memory_alignment(): """Return the alignment (in bytes) of memory allocations. This is enough to make sure a structure with pointers and 'double' fields is properly aligned.""" global _memory_alignment if _memory_alignment is None: S = getstruct( 'struct memory_alignment_test', """ struct memory_alignment_test { double d; void* p; }; """, []) result = ctypes.alignment(S) assert result & (result - 1) == 0, "not a power of two??" _memory_alignment = result return _memory_alignment
def __init__(self, fixlen=None, encoding=None): # TODO: Do this constructor better... if fixlen is None and encoding is None: # String() self.fixlen = None self.encoding = u'U8' elif isinstance(fixlen, _inttypes + (IntegerConstant,)) and \ encoding is None: # String(fixlen) if isinstance(fixlen, IntegerConstant): self.fixlen = fixlen.val else: self.fixlen = fixlen self.encoding = u'U8' elif isinstance(fixlen, _strtypes + (StringConstant,)) and \ encoding is None: # String('encoding') self.fixlen = None if isinstance(fixlen, StringConstant): self.encoding = fixlen.val else: self.encoding = unicode(fixlen) elif isinstance(fixlen, _inttypes + (IntegerConstant,)) and \ isinstance(encoding, _strtypes + (StringConstant,)): # String(fixlen, 'encoding') if isinstance(fixlen, IntegerConstant): self.fixlen = fixlen.val else: self.fixlen = fixlen if isinstance(encoding, StringConstant): self.encoding = encoding.val else: self.encoding = unicode(encoding) else: raise ValueError(('Unexpected types to String constructor ' '(%s, %s)') % (type(fixlen), type(encoding))) # Validate the encoding if not self.encoding in _canonical_string_encodings: raise ValueError('Unsupported string encoding %s' % repr(self.encoding)) # Put it in a canonical form self.encoding = _canonical_string_encodings[self.encoding] self._c_itemsize = 2 * ctypes.sizeof(ctypes.c_void_p) self._c_alignment = ctypes.alignment(ctypes.c_void_p)
def getInfo(self, fmt): ''' Takes a format string and returns a (size, alignment) tuple describing the size and alignment of the corresponding C type @param fmt: The format string to translate to a class @type fmt: string @return: A tuple containing the (size, alignment) of the C type @rtype: (integer, integer) tuple ''' if self.infotable.has_key(fmt) : return self.infotable[fmt] else : objclass = self.getClass(fmt) size = ctypes.sizeof(objclass) align = ctypes.alignment(objclass) self.infotable[fmt] = (size, align) return (size, align)
def getInfo(self, fmt): ''' Takes a format string and returns a (size, alignment) tuple describing the size and alignment of the corresponding C type @param fmt: The format string to translate to a class @type fmt: string @return: A tuple containing the (size, alignment) of the C type @rtype: (integer, integer) tuple ''' if self.infotable.has_key(fmt): return self.infotable[fmt] else: objclass = self.getClass(fmt) size = ctypes.sizeof(objclass) align = ctypes.alignment(objclass) self.infotable[fmt] = (size, align) return (size, align)
def ctype_alignment(c_type): if issubclass(c_type, ctypes.Structure): return max([ctype_alignment(fld_type) for fld_name, fld_type in c_type._fields_]) return ctypes.alignment(c_type)
uint_type = typedesc.FundamentalType("unsigned int", 32, 32) long_type = typedesc.FundamentalType("long int", 32, 32) ulong_type = typedesc.FundamentalType("long unsigned int", 32, 32) longlong_type = typedesc.FundamentalType("long long int", 64, 64) ulonglong_type = typedesc.FundamentalType("long long unsigned int", 64, 64) float_type = typedesc.FundamentalType("float", 32, 32) double_type = typedesc.FundamentalType("double", 64, 64) # basic COM data types BSTR_type = typedesc.Typedef("BSTR", PTR(wchar_t_type)) SCODE_type = typedesc.Typedef("SCODE", int_type) VARIANT_BOOL_type = typedesc.Typedef("VARIANT_BOOL", short_type) HRESULT_type = typedesc.Typedef("HRESULT", ulong_type) VARIANT_type = typedesc.Structure( "VARIANT", align=alignment(automation.VARIANT) * 8, members=[], bases=[], size=sizeof(automation.VARIANT) * 8 ) IDISPATCH_type = typedesc.Typedef("IDispatch", None) IUNKNOWN_type = typedesc.Typedef("IUnknown", None) DECIMAL_type = typedesc.Structure( "DECIMAL", align=alignment(automation.DECIMAL) * 8, members=[], bases=[], size=sizeof(automation.DECIMAL) * 8 ) def midlSAFEARRAY(typ): return typedesc.SAFEARRAYType(typ) # faked COM data types CURRENCY_type = longlong_type # slightly wrong; should be scaled by 10000 - use subclass of longlong? DATE_type = double_type # not *that* wrong...
def _alignment(cls): return ctypes.alignment(cls._ctype)
from ctypes.wintypes import BOOL, DWORD, HANDLE, LPVOID, LPCVOID # C:/PROGRA~1/MICROS~4/VC98/Include/winbase.h 223 class SECURITY_ATTRIBUTES(Structure): _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winbase.h 223 ('nLength', DWORD), ('lpSecurityDescriptor', LPVOID), ('bInheritHandle', BOOL), ] assert sizeof(SECURITY_ATTRIBUTES) == 12 or sizeof( SECURITY_ATTRIBUTES) == 24, sizeof(SECURITY_ATTRIBUTES) assert alignment(SECURITY_ATTRIBUTES) == 4 or alignment( SECURITY_ATTRIBUTES) == 8, alignment(SECURITY_ATTRIBUTES) PAGE_READWRITE = win32con.PAGE_READWRITE WAIT_TIMEOUT = win32con.WAIT_TIMEOUT PROCESS_ALL_ACCESS = win32con.PROCESS_ALL_ACCESS VIRTUAL_MEM = (win32con.MEM_RESERVE | win32con.MEM_COMMIT) LPCSTR = LPCTSTR = c_char_p LPWTSTR = c_wchar_p LPDWORD = PDWORD = POINTER(DWORD) LPTHREAD_START_ROUTINE = LPVOID LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES) OpenProcess = windll.kernel32.OpenProcess OpenProcess.restype = HANDLE OpenProcess.argtypes = (DWORD, BOOL, DWORD)
class JSON(Mono): """ JSON measure """ cls = MEASURE __slots__ = () def __str__(self): return "json" bool_ = CType("bool", 1, 1) char = CType("char", 1, 1) int8 = CType("int8", 1, 1) int16 = CType("int16", 2, ctypes.alignment(ctypes.c_int16)) int32 = CType("int32", 4, ctypes.alignment(ctypes.c_int32)) int64 = CType("int64", 8, ctypes.alignment(ctypes.c_int64)) # int is an alias for int32 int_ = int32 Type.register("int", int_) uint8 = CType("uint8", 1, 1) uint16 = CType("uint16", 2, ctypes.alignment(ctypes.c_uint16)) uint32 = CType("uint32", 4, ctypes.alignment(ctypes.c_uint32)) uint64 = CType("uint64", 8, ctypes.alignment(ctypes.c_uint64)) float16 = CType("float16", 2, ctypes.alignment(ctypes.c_uint16)) float32 = CType("float32", 4, ctypes.alignment(ctypes.c_float)) float64 = CType("float64", 8, ctypes.alignment(ctypes.c_double))
class JSON(Mono): """ JSON measure """ cls = MEASURE __slots__ = () def __str__(self): return 'json' bool_ = CType('bool', 1, 1) char = CType('char', 1, 1) int8 = CType('int8', 1, 1) int16 = CType('int16', 2, ctypes.alignment(ctypes.c_int16)) int32 = CType('int32', 4, ctypes.alignment(ctypes.c_int32)) int64 = CType('int64', 8, ctypes.alignment(ctypes.c_int64)) # int is an alias for int32 int_ = int32 Type.register('int', int_) uint8 = CType('uint8', 1, 1) uint16 = CType('uint16', 2, ctypes.alignment(ctypes.c_uint16)) uint32 = CType('uint32', 4, ctypes.alignment(ctypes.c_uint32)) uint64 = CType('uint64', 8, ctypes.alignment(ctypes.c_uint64)) float16 = CType('float16', 2, ctypes.alignment(ctypes.c_uint16)) float32 = CType('float32', 4, ctypes.alignment(ctypes.c_float)) float64 = CType('float64', 8, ctypes.alignment(ctypes.c_double))
def __init__(self): self.parameters = () self._c_itemsize = 2 * ctypes.sizeof(ctypes.c_void_p) self._c_alignment = ctypes.alignment(ctypes.c_void_p)
def test_struct_alignment(self): class X(Structure): x = ctypes.c_char * 3 self.assertEqual(ctypes.alignment(X), calcsize("s")) self.assertEqual(ctypes.sizeof(X), calcsize("3s")) class Y(Structure): x = ctypes.c_char * 3 y = ctypes.c_int self.assertEqual(ctypes.alignment(Y), ctypes.alignment(ctypes.c_int)) self.assertEqual(ctypes.sizeof(Y), calcsize("3si")) class SI(Structure): a = X b = Y self.assertEqual(ctypes.alignment(SI), max(ctypes.alignment(Y), ctypes.alignment(X))) self.assertEqual(ctypes.sizeof(SI), calcsize("3s0i 3si 0i")) class IS(Structure): b = Y a = X self.assertEqual(ctypes.alignment(SI), max(ctypes.alignment(X), ctypes.alignment(Y))) self.assertEqual(ctypes.sizeof(IS), calcsize("3si 3s 0i")) class XX(Structure): a = X b = X self.assertEqual(ctypes.alignment(XX), ctypes.alignment(X)) self.assertEqual(ctypes.sizeof(XX), calcsize("3s 3s 0s"))
# C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 class MOUSEINPUT(Structure): _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 ('dx', LONG), ('dy', LONG), ('mouseData', DWORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', DWORD), ] assert sizeof(MOUSEINPUT) == 24, sizeof(MOUSEINPUT) assert alignment(MOUSEINPUT) == 2, alignment(MOUSEINPUT) # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 class KEYBDINPUT(Structure): _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 ('wVk', WORD), ('wScan', WORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', DWORD), ]
(['in'], c_int, 'hwnd'), (['in'], POINTER(IUnknown), 'himl')), COMMETHOD([], HRESULT, 'SetOverlayIcon', (['in'], c_int, 'hwnd'), (['in'], POINTER(IUnknown), 'hIcon'), (['in'], WSTRING, 'pszDescription')), COMMETHOD([], HRESULT, 'SetThumbnailTooltip', (['in'], c_int, 'hwnd'), (['in'], WSTRING, 'pszTip')), COMMETHOD([], HRESULT, 'SetThumbnailClip', (['in'], c_int, 'hwnd'), (['in'], POINTER(tagRECT), 'prcClip'))] assert sizeof(tagTHUMBBUTTON) == 540, sizeof(tagTHUMBBUTTON) assert alignment(tagTHUMBBUTTON) == 4, alignment(tagTHUMBBUTTON) # based on http://stackoverflow.com/a/1744503/905256 class gPodderExtension: def __init__(self, container): self.container = container self.window_handle = None self.restart_warning = True def on_load(self): self.taskbar = client.CreateObject( '{56FDF344-FD6D-11d0-958A-006097C9A090}', interface=ITaskbarList3) self.taskbar.HrInit()
def _alignmentofinstances(self): from ctypes import alignment if not hasattr(self, '_alignment_'): self._alignment_ = max([alignment(field.ctype) for field in self._fieldtypes.values()] + [1]) return self._alignment_
uint_type = typedesc.FundamentalType("unsigned int", 32, 32) long_type = typedesc.FundamentalType("long int", 32, 32) ulong_type = typedesc.FundamentalType("long unsigned int", 32, 32) longlong_type = typedesc.FundamentalType("long long int", 64, 64) ulonglong_type = typedesc.FundamentalType("long long unsigned int", 64, 64) float_type = typedesc.FundamentalType("float", 32, 32) double_type = typedesc.FundamentalType("double", 64, 64) # basic COM data types BSTR_type = typedesc.Typedef("BSTR", PTR(wchar_t_type)) SCODE_type = typedesc.Typedef("SCODE", int_type) VARIANT_BOOL_type = typedesc.Typedef("VARIANT_BOOL", short_type) HRESULT_type = typedesc.Typedef("HRESULT", ulong_type) VARIANT_type = typedesc.Structure("VARIANT", align=alignment(automation.VARIANT)*8, members=[], bases=[], size=sizeof(automation.VARIANT)*8) IDISPATCH_type = typedesc.Typedef("IDispatch", None) IUNKNOWN_type = typedesc.Typedef("IUnknown", None) DECIMAL_type = typedesc.Structure("DECIMAL", align=alignment(automation.DECIMAL)*8, members=[], bases=[], size=sizeof(automation.DECIMAL)*8) def midlSAFEARRAY(typ): return typedesc.SAFEARRAYType(typ) # faked COM data types CURRENCY_type = longlong_type # slightly wrong; should be scaled by 10000 - use subclass of longlong? DATE_type = double_type # not *that* wrong...
(['in'], c_int, 'hwnd'), (['in'], POINTER(IUnknown), 'himl')), COMMETHOD([], HRESULT, 'SetOverlayIcon', (['in'], c_int, 'hwnd'), (['in'], POINTER(IUnknown), 'hIcon'), (['in'], WSTRING, 'pszDescription')), COMMETHOD([], HRESULT, 'SetThumbnailTooltip', (['in'], c_int, 'hwnd'), (['in'], WSTRING, 'pszTip')), COMMETHOD([], HRESULT, 'SetThumbnailClip', (['in'], c_int, 'hwnd'), (['in'], POINTER(tagRECT), 'prcClip'))] assert sizeof(tagTHUMBBUTTON) in [540, 552], sizeof(tagTHUMBBUTTON) assert alignment(tagTHUMBBUTTON) in [4, 8], alignment(tagTHUMBBUTTON) def consume_events(): """ consume pending events """ while Gtk.events_pending(): Gtk.main_iteration() # based on http://stackoverflow.com/a/1744503/905256 class gPodderExtension: def __init__(self, container): self.container = container self.window_handle = None self.restart_warning = True
def PTR(typ): return typedesc.PointerType(typ, sizeof(c_void_p)*8, alignment(c_void_p)*8)
def add_ivar(cls, name, vartype): "Add a new instance variable of type vartype to cls." return libobjc.class_addIvar( cls, ensure_bytes(name), sizeof(vartype), alignment(vartype), encoding_for_ctype(ctype_for_type(vartype)) )
(['in'], c_int, 'hwnd'), (['in'], c_uint, 'cButtons'), (['in'], POINTER(tagTHUMBBUTTON), 'pButton')), COMMETHOD([], HRESULT, 'ThumbBarSetImageList', (['in'], c_int, 'hwnd'), (['in'], POINTER(IUnknown), 'himl')), COMMETHOD([], HRESULT, 'SetOverlayIcon', (['in'], c_int, 'hwnd'), (['in'], POINTER(IUnknown), 'hIcon'), (['in'], WSTRING, 'pszDescription')), COMMETHOD([], HRESULT, 'SetThumbnailTooltip', (['in'], c_int, 'hwnd'), (['in'], WSTRING, 'pszTip')), COMMETHOD([], HRESULT, 'SetThumbnailClip', (['in'], c_int, 'hwnd'), (['in'], POINTER(tagRECT), 'prcClip')) ] assert sizeof(tagTHUMBBUTTON) == 540, sizeof(tagTHUMBBUTTON) assert alignment(tagTHUMBBUTTON) == 4, alignment(tagTHUMBBUTTON) # based on http://stackoverflow.com/a/1744503/905256 class gPodderExtension: def __init__(self, container): self.container = container self.window_handle = None self.restart_warning = True def on_load(self): self.taskbar = client.CreateObject( '{56FDF344-FD6D-11d0-958A-006097C9A090}', interface=ITaskbarList3) self.taskbar.HrInit() def on_unload(self):
return False # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 class MOUSEINPUT(Structure): _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 ('dx', LONG), ('dy', LONG), ('mouseData', DWORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', DWORD), ] assert sizeof(MOUSEINPUT) == 24, sizeof(MOUSEINPUT) assert alignment(MOUSEINPUT) == 2, alignment(MOUSEINPUT) # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 class KEYBDINPUT(Structure): _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 ('wVk', WORD), ('wScan', WORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', DWORD), ] assert sizeof(KEYBDINPUT) == 16, sizeof(KEYBDINPUT) assert alignment(KEYBDINPUT) == 2, alignment(KEYBDINPUT)
"""Allow iteration through coordinates""" yield self.x yield self.y def __getitem__(self, key): """Allow indexing of coordinates""" if key == 0 or key == -2: return self.x elif key == 1 or key == -1: return self.y else: raise IndexError("Illegal index") assert sizeof(POINT) == 8, sizeof(POINT) assert alignment(POINT) == 4, alignment(POINT) # ==================================================================== class RECT(Structure): """Wrap the RECT structure and add extra functionality""" _fields_ = [ # C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 287 ('left', LONG), ('top', LONG), ('right', LONG), ('bottom', LONG), ] # ----------------------------------------------------------------
class SocketCANTest(unittest.TestCase): def setUp(self): self._ctypes_sizeof = ctypes.sizeof self._ctypes_alignment = ctypes.alignment @patch("ctypes.sizeof") @patch("ctypes.alignment") def test_bcm_header_factory_32_bit_sizeof_long_4_alignof_long_4( self, ctypes_sizeof, ctypes_alignment): """This tests a 32-bit platform (ex. Debian Stretch on i386), where: * sizeof(long) == 4 * sizeof(long long) == 8 * alignof(long) == 4 * alignof(long long) == 4 """ def side_effect_ctypes_sizeof(value): type_to_size = { ctypes.c_longlong: 8, ctypes.c_long: 4, ctypes.c_uint8: 1, ctypes.c_uint16: 2, ctypes.c_uint32: 4, ctypes.c_uint64: 8, } return type_to_size[value] def side_effect_ctypes_alignment(value): type_to_alignment = { ctypes.c_longlong: 4, ctypes.c_long: 4, ctypes.c_uint8: 1, ctypes.c_uint16: 2, ctypes.c_uint32: 4, ctypes.c_uint64: 4, } return type_to_alignment[value] ctypes_sizeof.side_effect = side_effect_ctypes_sizeof ctypes_alignment.side_effect = side_effect_ctypes_alignment fields = [ ("opcode", ctypes.c_uint32), ("flags", ctypes.c_uint32), ("count", ctypes.c_uint32), ("ival1_tv_sec", ctypes.c_long), ("ival1_tv_usec", ctypes.c_long), ("ival2_tv_sec", ctypes.c_long), ("ival2_tv_usec", ctypes.c_long), ("can_id", ctypes.c_uint32), ("nframes", ctypes.c_uint32), ] BcmMsgHead = bcm_header_factory(fields) expected_fields = [ ("opcode", ctypes.c_uint32), ("flags", ctypes.c_uint32), ("count", ctypes.c_uint32), ("ival1_tv_sec", ctypes.c_long), ("ival1_tv_usec", ctypes.c_long), ("ival2_tv_sec", ctypes.c_long), ("ival2_tv_usec", ctypes.c_long), ("can_id", ctypes.c_uint32), ("nframes", ctypes.c_uint32), # We expect 4 bytes of padding ("pad_0", ctypes.c_uint8), ("pad_1", ctypes.c_uint8), ("pad_2", ctypes.c_uint8), ("pad_3", ctypes.c_uint8), ] self.assertEqual(expected_fields, BcmMsgHead._fields_) @patch("ctypes.sizeof") @patch("ctypes.alignment") def test_bcm_header_factory_32_bit_sizeof_long_4_alignof_long_long_8( self, ctypes_sizeof, ctypes_alignment): """This tests a 32-bit platform (ex. Raspbian Stretch on armv7l), where: * sizeof(long) == 4 * sizeof(long long) == 8 * alignof(long) == 4 * alignof(long long) == 8 """ def side_effect_ctypes_sizeof(value): type_to_size = { ctypes.c_longlong: 8, ctypes.c_long: 4, ctypes.c_uint8: 1, ctypes.c_uint16: 2, ctypes.c_uint32: 4, ctypes.c_uint64: 8, } return type_to_size[value] def side_effect_ctypes_alignment(value): type_to_alignment = { ctypes.c_longlong: 8, ctypes.c_long: 4, ctypes.c_uint8: 1, ctypes.c_uint16: 2, ctypes.c_uint32: 4, ctypes.c_uint64: 8, } return type_to_alignment[value] ctypes_sizeof.side_effect = side_effect_ctypes_sizeof ctypes_alignment.side_effect = side_effect_ctypes_alignment fields = [ ("opcode", ctypes.c_uint32), ("flags", ctypes.c_uint32), ("count", ctypes.c_uint32), ("ival1_tv_sec", ctypes.c_long), ("ival1_tv_usec", ctypes.c_long), ("ival2_tv_sec", ctypes.c_long), ("ival2_tv_usec", ctypes.c_long), ("can_id", ctypes.c_uint32), ("nframes", ctypes.c_uint32), ] BcmMsgHead = bcm_header_factory(fields) expected_fields = [ ("opcode", ctypes.c_uint32), ("flags", ctypes.c_uint32), ("count", ctypes.c_uint32), ("ival1_tv_sec", ctypes.c_long), ("ival1_tv_usec", ctypes.c_long), ("ival2_tv_sec", ctypes.c_long), ("ival2_tv_usec", ctypes.c_long), ("can_id", ctypes.c_uint32), ("nframes", ctypes.c_uint32), # We expect 4 bytes of padding ("pad_0", ctypes.c_uint8), ("pad_1", ctypes.c_uint8), ("pad_2", ctypes.c_uint8), ("pad_3", ctypes.c_uint8), ] self.assertEqual(expected_fields, BcmMsgHead._fields_) @patch("ctypes.sizeof") @patch("ctypes.alignment") def test_bcm_header_factory_64_bit_sizeof_long_8_alignof_long_8( self, ctypes_sizeof, ctypes_alignment): """This tests a 64-bit platform (ex. Ubuntu 18.04 on x86_64), where: * sizeof(long) == 8 * sizeof(long long) == 8 * alignof(long) == 8 * alignof(long long) == 8 """ def side_effect_ctypes_sizeof(value): type_to_size = { ctypes.c_longlong: 8, ctypes.c_long: 8, ctypes.c_uint8: 1, ctypes.c_uint16: 2, ctypes.c_uint32: 4, ctypes.c_uint64: 8, } return type_to_size[value] def side_effect_ctypes_alignment(value): type_to_alignment = { ctypes.c_longlong: 8, ctypes.c_long: 8, ctypes.c_uint8: 1, ctypes.c_uint16: 2, ctypes.c_uint32: 4, ctypes.c_uint64: 8, } return type_to_alignment[value] ctypes_sizeof.side_effect = side_effect_ctypes_sizeof ctypes_alignment.side_effect = side_effect_ctypes_alignment fields = [ ("opcode", ctypes.c_uint32), ("flags", ctypes.c_uint32), ("count", ctypes.c_uint32), ("ival1_tv_sec", ctypes.c_long), ("ival1_tv_usec", ctypes.c_long), ("ival2_tv_sec", ctypes.c_long), ("ival2_tv_usec", ctypes.c_long), ("can_id", ctypes.c_uint32), ("nframes", ctypes.c_uint32), ] BcmMsgHead = bcm_header_factory(fields) expected_fields = [ ("opcode", ctypes.c_uint32), ("flags", ctypes.c_uint32), ("count", ctypes.c_uint32), # We expect 4 bytes of padding ("pad_0", ctypes.c_uint8), ("pad_1", ctypes.c_uint8), ("pad_2", ctypes.c_uint8), ("pad_3", ctypes.c_uint8), ("ival1_tv_sec", ctypes.c_long), ("ival1_tv_usec", ctypes.c_long), ("ival2_tv_sec", ctypes.c_long), ("ival2_tv_usec", ctypes.c_long), ("can_id", ctypes.c_uint32), ("nframes", ctypes.c_uint32), ] self.assertEqual(expected_fields, BcmMsgHead._fields_) @unittest.skipIf( not (ctypes.sizeof(ctypes.c_long) == 4 and ctypes.alignment(ctypes.c_long) == 4), "Should only run on platforms where sizeof(long) == 4 and alignof(long) == 4", ) def test_build_bcm_header_sizeof_long_4_alignof_long_4(self): expected_result = (b"\x02\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x01\x04\x00\x00" b"\x01\x00\x00\x00\x00\x00\x00\x00") self.assertEqual( expected_result, build_bcm_header( opcode=CAN_BCM_TX_DELETE, flags=0, count=0, ival1_seconds=0, ival1_usec=0, ival2_seconds=0, ival2_usec=0, can_id=0x401, nframes=1, ), ) @unittest.skipIf( not (ctypes.sizeof(ctypes.c_long) == 8 and ctypes.alignment(ctypes.c_long) == 8), "Should only run on platforms where sizeof(long) == 8 and alignof(long) == 8", ) def test_build_bcm_header_sizeof_long_8_alignof_long_8(self): expected_result = (b"\x02\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x00\x00\x00\x00" b"\x01\x04\x00\x00\x01\x00\x00\x00") self.assertEqual( expected_result, build_bcm_header( opcode=CAN_BCM_TX_DELETE, flags=0, count=0, ival1_seconds=0, ival1_usec=0, ival2_seconds=0, ival2_usec=0, can_id=0x401, nframes=1, ), ) def test_build_bcm_tx_delete_header(self): can_id = 0x401 flags = 0 bcm_buffer = build_bcm_tx_delete_header(can_id=can_id, flags=flags) result = BcmMsgHead.from_buffer_copy(bcm_buffer) self.assertEqual(CAN_BCM_TX_DELETE, result.opcode) self.assertEqual(flags, result.flags) self.assertEqual(0, result.count) self.assertEqual(0, result.ival1_tv_sec) self.assertEqual(0, result.ival1_tv_usec) self.assertEqual(0, result.ival2_tv_sec) self.assertEqual(0, result.ival2_tv_usec) self.assertEqual(can_id, result.can_id) self.assertEqual(1, result.nframes) def test_build_bcm_transmit_header_initial_period_0(self): can_id = 0x401 flags = 0 count = 42 bcm_buffer = build_bcm_transmit_header( can_id=can_id, count=count, initial_period=0, subsequent_period=2, msg_flags=flags, ) result = BcmMsgHead.from_buffer_copy(bcm_buffer) self.assertEqual(CAN_BCM_TX_SETUP, result.opcode) # SETTIMER and STARTTIMER should be added to the initial flags self.assertEqual(flags | SETTIMER | STARTTIMER, result.flags) self.assertEqual(count, result.count) self.assertEqual(0, result.ival1_tv_sec) self.assertEqual(0, result.ival1_tv_usec) self.assertEqual(2, result.ival2_tv_sec) self.assertEqual(0, result.ival2_tv_usec) self.assertEqual(can_id, result.can_id) self.assertEqual(1, result.nframes) def test_build_bcm_transmit_header_initial_period_1_24(self): can_id = 0x401 flags = 0 count = 42 bcm_buffer = build_bcm_transmit_header( can_id=can_id, count=count, initial_period=1.24, subsequent_period=2, msg_flags=flags, ) result = BcmMsgHead.from_buffer_copy(bcm_buffer) self.assertEqual(CAN_BCM_TX_SETUP, result.opcode) # SETTIMER, STARTTIMER, TX_COUNTEVT should be added to the initial flags self.assertEqual(flags | SETTIMER | STARTTIMER | TX_COUNTEVT, result.flags) self.assertEqual(count, result.count) self.assertEqual(1, result.ival1_tv_sec) self.assertEqual(240000, result.ival1_tv_usec) self.assertEqual(2, result.ival2_tv_sec) self.assertEqual(0, result.ival2_tv_usec) self.assertEqual(can_id, result.can_id) self.assertEqual(1, result.nframes) def test_build_bcm_update_header(self): can_id = 0x401 flags = 0 bcm_buffer = build_bcm_update_header(can_id=can_id, msg_flags=flags) result = BcmMsgHead.from_buffer_copy(bcm_buffer) self.assertEqual(CAN_BCM_TX_SETUP, result.opcode) self.assertEqual(flags, result.flags) self.assertEqual(0, result.count) self.assertEqual(0, result.ival1_tv_sec) self.assertEqual(0, result.ival1_tv_usec) self.assertEqual(0, result.ival2_tv_sec) self.assertEqual(0, result.ival2_tv_usec) self.assertEqual(can_id, result.can_id) self.assertEqual(1, result.nframes)
#!/usr/bin/python # -*- coding: utf-8 -*- import ctypes """ ctypes.alignment(obj_or_type) Returns the alignment requirements of a ctypes type. obj_or_type must be a ctypes type or instance. """ var = ctypes.c_uint32(0x54) print(ctypes.alignment(var))
def __ne__(cls, other): return not (cls == other) def __hash__(cls): return hash((cls.name, cls.n)) #------------------------------------------------------------------------ # Unit Types #------------------------------------------------------------------------ bool_ = CType('bool', 1, 1) char = CType('char', 1, 1) int8 = CType('int8', 1, 1) int16 = CType('int16', 2, ctypes.alignment(ctypes.c_int16)) int32 = CType('int32', 4, ctypes.alignment(ctypes.c_int32)) int64 = CType('int64', 8, ctypes.alignment(ctypes.c_int64)) uint8 = CType('uint8', 1, 1) uint16 = CType('uint16', 2, ctypes.alignment(ctypes.c_uint16)) uint32 = CType('uint32', 4, ctypes.alignment(ctypes.c_uint32)) uint64 = CType('uint64', 8, ctypes.alignment(ctypes.c_uint64)) float16 = CType('float16', 2, ctypes.alignment(ctypes.c_uint16)) float32 = CType('float32', 4, ctypes.alignment(ctypes.c_float)) float64 = CType('float64', 8, ctypes.alignment(ctypes.c_double)) #float128 = CType('float128', 16) cfloat32 = CType('cfloat32', 8, ctypes.alignment(ctypes.c_float)) cfloat64 = CType('cfloat64', 16, ctypes.alignment(ctypes.c_double))
# C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 class MOUSEINPUT(ctypes.Structure): "Needed for complete definition of INPUT structure - not used" _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 ('dx', LONG), ('dy', LONG), ('mouseData', DWORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', DWORD), ] assert ctypes.sizeof(MOUSEINPUT) == 24, ctypes.sizeof(MOUSEINPUT) assert ctypes.alignment(MOUSEINPUT) == 2, ctypes.alignment(MOUSEINPUT) # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 class KEYBDINPUT(ctypes.Structure): "A particular keyboard event" _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 ('wVk', WORD), ('wScan', WORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', DWORD), ] assert ctypes.sizeof(KEYBDINPUT) == 16, ctypes.sizeof(KEYBDINPUT)
uint_type = typedesc.FundamentalType("unsigned int", 32, 32) long_type = typedesc.FundamentalType("long int", 32, 32) ulong_type = typedesc.FundamentalType("long unsigned int", 32, 32) longlong_type = typedesc.FundamentalType("long long int", 64, 64) ulonglong_type = typedesc.FundamentalType("long long unsigned int", 64, 64) float_type = typedesc.FundamentalType("float", 32, 32) double_type = typedesc.FundamentalType("double", 64, 64) # basic COM data types BSTR_type = typedesc.Typedef("BSTR", PTR(wchar_t_type)) SCODE_type = typedesc.Typedef("SCODE", int_type) VARIANT_BOOL_type = typedesc.Typedef("VARIANT_BOOL", short_type) HRESULT_type = typedesc.Typedef("HRESULT", ulong_type) VARIANT_type = typedesc.Structure("VARIANT", align=alignment(automation.VARIANT) * 8, members=[], bases=[], size=sizeof(automation.VARIANT) * 8) IDISPATCH_type = typedesc.Typedef("IDispatch", None) IUNKNOWN_type = typedesc.Typedef("IUnknown", None) def midlSAFEARRAY(typ): return typedesc.SAFEARRAYType(typ) # faked COM data types CURRENCY_type = longlong_type # slightly wrong; should be scaled by 10000 - use subclass of longlong? DATE_type = double_type # not *that* wrong... DECIMAL_type = double_type # wrong - it's a 12 byte structure (or was it 16 bytes?)
HTREEITEM = LONG_PTR #LONG HWND = LONG_PTR #LONG LPARAM = LONG_PTR WPARAM = UINT_PTR class POINT(Structure): _pack_ = 4 _fields_ = [ # C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 307 ('x', LONG), ('y', LONG), ] assert sizeof(POINT) == 8, sizeof(POINT) assert alignment(POINT) == 4, alignment(POINT) # ==================================================================== class RECT(Structure): """Wrap the RECT structure and add extra functionality""" _fields_ = [ # C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 287 ('left', LONG), ('top', LONG), ('right', LONG), ('bottom', LONG), ]
uint_type = typedesc.FundamentalType("unsigned int", 32, 32) long_type = typedesc.FundamentalType("long int", 32, 32) ulong_type = typedesc.FundamentalType("long unsigned int", 32, 32) longlong_type = typedesc.FundamentalType("long long int", 64, 64) ulonglong_type = typedesc.FundamentalType("long long unsigned int", 64, 64) float_type = typedesc.FundamentalType("float", 32, 32) double_type = typedesc.FundamentalType("double", 64, 64) # basic COM data types BSTR_type = typedesc.Typedef("BSTR", PTR(wchar_t_type)) SCODE_type = typedesc.Typedef("SCODE", int_type) VARIANT_BOOL_type = typedesc.Typedef("VARIANT_BOOL", short_type) HRESULT_type = typedesc.Typedef("HRESULT", ulong_type) VARIANT_type = typedesc.Structure("VARIANT", align=alignment(automation.VARIANT)*8, members=[], bases=[], size=sizeof(automation.VARIANT)*8) IDISPATCH_type = typedesc.Typedef("IDispatch", None) IUNKNOWN_type = typedesc.Typedef("IUnknown", None) def midlSAFEARRAY(typ): return typedesc.SAFEARRAYType(typ) # faked COM data types CURRENCY_type = longlong_type # slightly wrong; should be scaled by 10000 - use subclass of longlong? DATE_type = double_type # not *that* wrong... DECIMAL_type = double_type # wrong - it's a 12 byte structure (or was it 16 bytes?) COMTYPES = { automation.VT_I2: short_type, # 2
_pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4283 ('dx', LONG), ('dy', LONG), ('mouseData', DWORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', ctypes.POINTER(ctypes.c_ulong)), ] assert ctypes.sizeof(MOUSEINPUT) == 24 or ctypes.sizeof( MOUSEINPUT) == 28, ctypes.sizeof(MOUSEINPUT) if sysinfo.is_x64_Python(): assert ctypes.alignment(MOUSEINPUT) == 4, ctypes.alignment(MOUSEINPUT) else: assert ctypes.alignment(MOUSEINPUT) == 2, ctypes.alignment(MOUSEINPUT) # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 class KEYBDINPUT(ctypes.Structure): "A particular keyboard event" if sysinfo.is_x64_Python(): _pack_ = 4 else: _pack_ = 2 _fields_ = [ # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292 ('wVk', WORD), ('wScan', WORD),