Skip to content

Instantly share code, notes, and snippets.

@andelf
Created March 31, 2012 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andelf/2264961 to your computer and use it in GitHub Desktop.
Save andelf/2264961 to your computer and use it in GitHub Desktop.
a Structure impl support both ctypes and struct.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# FileName : cstruct.py
# Author : Feather.et.ELF <andelf@gmail.com>
# Created : Tue Feb 28 23:06:44 2012 by Feather.et.ELF
# Copyright : Feather Workshop (c) 2012
# Description : mcpack v1 v2
# Time-stamp: <2012-03-31 18:58:42 andelf>
import struct
import ctypes
class Structure(ctypes.Structure):
def __init__(self, *args, **kwargs):
if kwargs:
if args:
raise TypeError("can handle **kwargs and *args at a time.")
ctypes.Structure.__init__(self, **kwargs)
else:
for i, field in enumerate(self._fields_):
field_name = field[0]
setattr(self, field_name, args[i])
def to_str(self):
fmt = ['=']
values = []
Ctype = ctypes.Array.__base__
# from ctypes types to struct format
field_map = {ctypes.c_char: 'c',
ctypes.c_uint8: 'B',
ctypes.c_uint16: 'H',
ctypes.c_uint32: 'I',
ctypes.c_ulong: 'L',
ctypes.c_ulonglong: 'Q',
ctypes.c_int8: 'b',
ctypes.c_int16: 'h',
ctypes.c_int32: 'i',
ctypes.c_long: 'l',
ctypes.c_longlong: 'q',
ctypes.c_float: 'f',
ctypes.c_double: 'd',
ctypes.c_bool: '?',
# add more here
}
# special handling for array
field_array_map = field_map.copy()
field_array_map.update({ctypes.c_char: 's'})
for key, tp in self._fields_:
# construct fmt str
if issubclass(tp, ctypes.Array):
size = tp._length_
orig_tp = tp._type_
fmt.append("%d%s" % (size, field_array_map[orig_tp]))
elif issubclass(tp, Ctype):
fmt.append(field_map[tp])
else:
raise TypeError('Unkown type code: %s' % tp)
values.append(getattr(self, key))
fmt = ''.join(fmt)
return struct.pack(fmt, *values)
@classmethod
def from_str(cls, string):
assert len(string) == ctypes.sizeof(cls), \
"string length error! not fit %d" % ctypes.sizeof(cls)
buf = ctypes.create_string_buffer(string)
inst = cls.from_buffer(buf)
return inst
@andelf
Copy link
Author

andelf commented Mar 31, 2012

haven't support embed struct yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment