[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