[pypy-svn] r78111 - pypy/trunk/lib_pypy/_ctypes
arigo at codespeak.net
arigo at codespeak.net
Wed Oct 20 11:37:31 CEST 2010
Author: arigo
Date: Wed Oct 20 11:37:29 2010
New Revision: 78111
Modified:
pypy/trunk/lib_pypy/_ctypes/structure.py
pypy/trunk/lib_pypy/_ctypes/union.py
Log:
My best fix to ctypes ever (which I hope is correct):
kill most of union.py, and just do it by importing from
structure.py.
Modified: pypy/trunk/lib_pypy/_ctypes/structure.py
==============================================================================
--- pypy/trunk/lib_pypy/_ctypes/structure.py (original)
+++ pypy/trunk/lib_pypy/_ctypes/structure.py Wed Oct 20 11:37:29 2010
@@ -7,7 +7,7 @@
def round_up(size, alignment):
return (size + alignment - 1) & -alignment
-def size_alignment_pos(fields):
+def size_alignment_pos(fields, is_union=False):
import ctypes
size = 0
alignment = 1
@@ -15,14 +15,19 @@
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
+ if is_union:
+ pos.append(0)
+ size = max(size, fieldsize)
+ else:
+ size = round_up(size, fieldalignment)
+ pos.append(size)
+ size += fieldsize
size = round_up(size, alignment)
return size, alignment, pos
-def names_and_fields(_fields_, superclass, zero_offset=False, anon=None):
+def names_and_fields(_fields_, superclass, zero_offset=False, anon=None,
+ is_union=False):
if isinstance(_fields_, tuple):
_fields_ = list(_fields_)
for _, tp in _fields_:
@@ -36,7 +41,7 @@
rawfields = [(name, ctype._ffishape)
for name, ctype in all_fields]
if not zero_offset:
- _, _, pos = size_alignment_pos(all_fields)
+ _, _, pos = size_alignment_pos(all_fields, is_union)
else:
pos = [0] * len(all_fields)
fields = {}
@@ -73,8 +78,8 @@
# ________________________________________________________________
-def _set_shape(tp, rawfields):
- tp._ffistruct = _rawffi.Structure(rawfields)
+def _set_shape(tp, rawfields, is_union=False):
+ tp._ffistruct = _rawffi.Structure(rawfields, is_union)
tp._ffiargshape = tp._ffishape = (tp._ffistruct, 1)
tp._fficompositesize = tp._ffistruct.size
@@ -92,13 +97,14 @@
raise AttributeError("Structure or union cannot contain itself")
self._names, rawfields, self._fieldtypes = names_and_fields(
value, self.__bases__[0], False,
- self.__dict__.get('_anonymous_', None))
+ self.__dict__.get('_anonymous_', None), self._is_union)
_CDataMeta.__setattr__(self, '_fields_', value)
- _set_shape(self, rawfields)
+ _set_shape(self, rawfields, self._is_union)
return
_CDataMeta.__setattr__(self, name, value)
-class StructureMeta(_CDataMeta):
+class StructOrUnionMeta(_CDataMeta):
+
def __new__(self, name, cls, typedict):
res = type.__new__(self, name, cls, typedict)
if '_fields_' in typedict:
@@ -109,8 +115,8 @@
raise AttributeError("Anonymous field not found")
res._names, rawfields, res._fieldtypes = names_and_fields(
typedict['_fields_'], cls[0], False,
- typedict.get('_anonymous_', None))
- _set_shape(res, rawfields)
+ typedict.get('_anonymous_', None), self._is_union)
+ _set_shape(res, rawfields, self._is_union)
return res
@@ -150,8 +156,8 @@
res.__dict__['_index'] = -1
return res
-class Structure(_CData):
- __metaclass__ = StructureMeta
+class StructOrUnion(_CData):
+ __metaclass__ = StructOrUnionMeta
def __new__(cls, *args, **kwds):
if not hasattr(cls, '_ffistruct'):
@@ -213,3 +219,10 @@
def _get_buffer_value(self):
return self._buffer.buffer
+
+
+class StructureMeta(StructOrUnionMeta):
+ _is_union = False
+
+class Structure(StructOrUnion):
+ __metaclass__ = StructureMeta
Modified: pypy/trunk/lib_pypy/_ctypes/union.py
==============================================================================
--- pypy/trunk/lib_pypy/_ctypes/union.py (original)
+++ pypy/trunk/lib_pypy/_ctypes/union.py Wed Oct 20 11:37:29 2010
@@ -1,118 +1,7 @@
+from _ctypes import structure
+class UnionMeta(structure.StructOrUnionMeta):
+ _is_union = True
-import _rawffi
-from _ctypes.basics import _CData, _CDataMeta, store_reference, keepalive_key
-from _ctypes.basics import ensure_objects
-from _ctypes.structure import round_up, names_and_fields, struct_getattr,\
- struct_setattr
-
-
-def _set_shape(tp):
- size = tp._sizeofinstances()
- alignment = tp._alignmentofinstances()
- tp._ffiopaque = _rawffi.Structure((size, alignment)) # opaque
- tp._ffiargshape = tp._ffishape = (tp._ffiopaque, 1)
- tp._fficompositesize = tp._ffiopaque.size
- # we need to create an array of size one for each
- # of our elements
- tp._ffiarrays = {}
- for name, field in tp._fieldtypes.iteritems():
- tp._ffiarrays[name] = _rawffi.Array(field.ctype._ffishape)
-
-class UnionMeta(_CDataMeta):
- def __new__(self, name, cls, typedict):
- res = type.__new__(self, name, cls, typedict)
- if '_fields_' in typedict:
- res._names, rawfields, res._fieldtypes = names_and_fields(
- typedict['_fields_'], cls[0], True,
- typedict.get('_anonymous_', None))
- _set_shape(res)
-
- def __init__(self): # don't allow arguments by now
- if not hasattr(self, '_ffiarrays'):
- raise TypeError("Cannot instantiate union, has no type")
- # malloc size
- size = self.__class__._sizeofinstances()
- self.__dict__['_objects'] = {}
- self.__dict__['_buffer'] = self._ffiopaque(autofree=True)
- res.__init__ = __init__
- return res
-
- def _sizeofinstances(self):
- if not hasattr(self, '_size_'):
- self._size_ = max([field.size for field in
- self._fieldtypes.values()] + [0])
- return self._size_
-
- 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_
-
- __getattr__ = struct_getattr
-
- def __setattr__(self, name, value):
- if name == '_fields_':
- if self.__dict__.get('_fields_', None):
- raise AttributeError("_fields_ is final")
- if self in [v for k, v in value]:
- raise AttributeError("Union cannot contain itself")
- self._names, rawfields, self._fieldtypes = names_and_fields(
- value, self.__bases__[0], True,
- self.__dict__.get('_anonymous_', None))
- _CDataMeta.__setattr__(self, '_fields_', value)
- _set_shape(self)
- _CDataMeta.__setattr__(self, name, value)
-
- def _CData_output(self, resarray, base=None, index=-1):
- res = self.__new__(self)
- ffiopaque = self._ffiopaque.fromaddress(resarray.buffer)
- res.__dict__['_buffer'] = ffiopaque
- res.__dict__['_base'] = base
- res.__dict__['_index'] = index
- return res
-
- def _CData_retval(self, resbuffer):
- res = self.__new__(self)
- res.__dict__['_buffer'] = resbuffer
- res.__dict__['_base'] = None
- res.__dict__['_index'] = -1
- return res
-
-
-class Union(_CData):
+class Union(structure.StructOrUnion):
__metaclass__ = UnionMeta
-
- def __getattr__(self, name):
- try:
- field = self._fieldtypes[name]
- except KeyError:
- raise AttributeError(name)
- fieldtype = field.ctype
- val = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)
- offset = field.num
- return fieldtype._CData_output(val, self, offset)
-
- def __setattr__(self, name, value):
- try:
- field = self._fieldtypes[name]
- except KeyError:
- raise AttributeError(name)
- fieldtype = field.ctype
- cobj = fieldtype.from_param(value)
- if ensure_objects(cobj) is not None:
- key = keepalive_key(field.num)
- store_reference(self, key, cobj._objects)
- arg = cobj._get_buffer_value()
- if fieldtype._fficompositesize is not None:
- from ctypes import memmove
- dest = self._buffer.buffer
- memmove(dest, arg, fieldtype._fficompositesize)
- else:
- buf = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)
- buf[0] = arg
-
- def _get_buffer_value(self):
- return self._buffer.buffer
More information about the Pypy-commit
mailing list