[pypy-svn] r50572 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes

fijal at codespeak.net fijal at codespeak.net
Sun Jan 13 23:26:41 CET 2008


Author: fijal
Date: Sun Jan 13 23:26:40 2008
New Revision: 50572

Modified:
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py
Log:
(arigo, fijal) ARGH.


Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py	Sun Jan 13 23:26:40 2008
@@ -1,9 +1,9 @@
 
 import _ffi
 
-from _ctypes.basics import _CData, cdata_from_address
+from _ctypes.basics import _CData, cdata_from_address, _CDataMeta
 
-class ArrayMeta(type):
+class ArrayMeta(_CDataMeta):
     def __new__(self, name, cls, typedict):
         res = type.__new__(self, name, cls, typedict)
         res._ffiletter = 'P'
@@ -19,14 +19,23 @@
                         i += 1
                     return "".join(res)
                 def setvalue(self, val):
-                    for i in range(min(len(val), self._length_)):
+                    # we don't want to have buffers here
+                    import ctypes
+                    if len(val) > self._length_:
+                        raise ValueError("%s too long" % (val,))
+                    for i in range(len(val)):
                         self[i] = val[i]
-                    self[len(val)] = '\x00'
+                    if len(val) < self._length_:
+                        self[len(val)] = '\x00'
                 res.value = property(getvalue, setvalue)
 
                 def getraw(self):
                     return "".join([self[i] for i in range(self._length_)])
-                res.raw = property(getraw)
+
+                def setraw(self, buffer):
+                    for i in range(len(buffer)):
+                        self[i] = buffer[i]
+                res.raw = property(getraw, setraw)
         else:
             res._ffiarray = None
         return res
@@ -65,12 +74,11 @@
         return "".join([self[i] for i in range(start, stop)])
     
     def __setitem__(self, item, value):
+        from ctypes import _SimpleCData
         if isinstance(item, slice):
             self._slice_setitem(item, value)
-        # XXX
-        from ctypes import _SimpleCData
-        if isinstance(value, _SimpleCData):
-            value = value.value
+            return
+        value = self._type_.from_param(value).value
         item = self._fix_item(item)
         if self._type_._ffiletter == 'c' and len(value) > 1:
             raise TypeError("Expected strings of length 1")

Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py	Sun Jan 13 23:26:40 2008
@@ -1,20 +1,28 @@
 
 import _ffi
 
+class _CDataMeta(type):
+    def from_param(self, value):
+        if isinstance(value, self):
+            return value
+        raise TypeError("Wrong type")    
+
 class _CData(object):
     """ The most basic object for all ctypes types
     """
+    __metaclass__ = _CDataMeta
+    
     def __ctypes_from_outparam__(self):
         return self
 
-class CArgObject(object):
-    def __init__(self, letter, raw_value, _type):
-        self.ffiletter = letter
-        self.raw_value = raw_value
-        self._type = _type
+#class CArgObject(object):
+#    def __init__(self, letter, raw_value, _type):
+#        self.ffiletter = letter
+#        self._array = raw_value
+#        self._type = _type
 
-    def __repr__(self):
-        return "<cparam '%s' %r>" % (self.ffiletter, self.raw_value)
+#    def __repr__(self):
+#        return "<cparam '%s' %r>" % (self.ffiletter, self._array[0])
 
 
 TP_TO_FFITP = {    # XXX this should die; interp_ffi should just accept them
@@ -22,7 +30,6 @@
         'z': 's',
 }
 
-
 def sizeof(tp):
     ffitp = tp._type_
     return _ffi.sizeof(TP_TO_FFITP.get(ffitp, ffitp))
@@ -35,7 +42,7 @@
     from ctypes import pointer, _SimpleCData
     if not isinstance(cdata, _SimpleCData):
         raise TypeError("expected CData instance")
-    return pointer(cdata)._as_ffi()
+    return pointer(cdata)
 
 def cdata_from_address(self, address):
     instance = self.__new__(self)

Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py	Sun Jan 13 23:26:40 2008
@@ -1,68 +1,59 @@
 import _ffi
-from _ctypes.basics import CArgObject
 
-class CFuncPtrType(type):
+from _ctypes.basics import _CData, _CDataMeta
+
+class CFuncPtrType(_CDataMeta):
     # XXX write down here defaults and such things
     pass
 
-class CFuncPtr(object):
+class CFuncPtr(_CData):
     __metaclass__ = CFuncPtrType
-    argtypes = None
-    _argtypes = None
-    restype = None
-    _restype = None
-    def __init__(self, stuff):
-        if isinstance(stuff, tuple):
-            name, dll = stuff
-            self.name = name
-            self.dll = dll
-            self._funcptr = None
+
+    _argtypes_ = None
+    _restype_ = None
+
+    def _getargtypes(self):
+        return self._argtypes_
+    def _setargtypes(self, argtypes):
+        self._argtypes_ = argtypes    
+    argtypes = property(_getargtypes, _setargtypes)
+
+    def _getrestype(self):
+        return self._restype_
+    def _setrestype(self, restype):
+        self._restype_ = restype    
+    restype = property(_getrestype, _setrestype)    
+
+    def __init__(self, address_or_name_and_dll):
+        if isinstance(address_or_name_and_dll, tuple):
+            self.name, self.dll = address_or_name_and_dll
         else:
             self.name = None
-            self.dll = None
 
     def __call__(self, *args):
-        import ctypes
-        if self.restype is None:
-            # XXX point to default instead
-            self.restype = ctypes.c_int
-        if self.argtypes is not None:
-            if len(args) != len(self.argtypes):
-                raise TypeError("%s takes %s arguments, given %s" %
-                                (self.name, len(self.argtypes), len(args)))
-        funcptr = self._getfuncptr(args)
-        argvalues = [tp.from_param(arg).raw_value for tp, arg in zip(self._argtypes, args)]
-        res = funcptr(*argvalues)
-        if issubclass(self.restype, ctypes._SimpleCData):
-            return res
-        else:
-            # XXX pointers
-            return self.restype(res)
+        if self.name is None:
+            raise NotImplementedError("Creation of function pointer to pure addresses is not implemented")
+        argtypes = self._argtypes_
+        if argtypes is None:
+            argtypes = self._guess_argtypes(args)
+        restype = self._restype_
+        funcptr = self._getfuncptr(argtypes, restype)
+        res = funcptr(*self._wrap_args(argtypes, args))
+        if restype is not None:
+            return restype(res).__ctypes_from_outparam__()
 
-    def _getfuncptr(self, args):
-        if self._funcptr is not None:
-            if (self.argtypes is self._argtypes
-                and self.restype is self._restype):
-                return self._funcptr
-        if self.argtypes is None:
-            argtypes = self._guess_magic_args(args)
-        else:
-            argtypes = self.argtypes
-        argtps = [argtype._ffiletter for argtype in argtypes]
-        restp = self.restype._ffiletter
-        self._funcptr = funcptr = self.dll._handle.ptr(self.name, argtps, restp)
-        self._argtypes = argtypes
-        self._restype = self.restype
-        return funcptr
+    def _getfuncptr(self, argtypes, restype):
+        argletters = [arg._ffiletter for arg in argtypes]
+        return self.dll._handle.ptr(self.name, argletters, restype._ffiletter)
 
-    def _guess_magic_args(self, args):
-        import _ctypes
+    def _guess_argtypes(self, args):
+        from _ctypes import _CData
         res = []
         for arg in args:
-            if isinstance(arg, _ctypes._CData):
-                res.append(type(arg))
-            elif isinstance(arg, CArgObject):
-                res.append(arg._type)
-            else:
-                raise TypeError("Cannot convert %s" % arg)
+            assert isinstance(arg, _CData)
+            res.append(type(arg))
         return res
+
+    def _wrap_args(self, argtypes, args):
+        return [argtype.from_param(arg)._array[0] for argtype, arg in
+                zip(argtypes, args)]

Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py	Sun Jan 13 23:26:40 2008
@@ -1,10 +1,10 @@
 
 import _ffi
-from _ctypes.basics import _CData, CArgObject, cdata_from_address
+from _ctypes.basics import _CData, _CDataMeta, cdata_from_address
 
 DEFAULT_VALUE = object()
 
-class PointerType(type):
+class PointerType(_CDataMeta):
     def __new__(self, name, cls, typedict):
         d = dict(
             size       = _ffi.sizeof('P'),
@@ -31,13 +31,6 @@
 
     from_address = cdata_from_address
 
-    def from_param(self, param):
-        # XXX think deeper about that
-        if isinstance(param, CArgObject):
-            return param
-        else:
-            return self.from_address(param._array.buffer)._as_ffi()
-
 class _Pointer(_CData):
     __metaclass__ = PointerType
 
@@ -55,10 +48,6 @@
         else:
             self._array[0] = value._array
 
-    def _as_ffi(self):
-        # XXX performance
-        return CArgObject('P', self._type_.from_address(self._array[0])._array, type(self))
-
     def __getitem__(self, item):
         assert item == 0
         return self._type_.from_address(self._array[0]).__ctypes_from_outparam__()

Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py	Sun Jan 13 23:26:40 2008
@@ -2,7 +2,7 @@
 
 SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv"
 
-from _ctypes.basics import _CData, CArgObject, cdata_from_address, TP_TO_FFITP
+from _ctypes.basics import _CData, _CDataMeta, cdata_from_address, TP_TO_FFITP
 from _ctypes.array import create_array_type
 
 class NULL(object):
@@ -31,7 +31,7 @@
  
 DEFAULT_VALUE = object()
 
-class SimpleType(type):
+class SimpleType(_CDataMeta):
     def __new__(self, name, bases, dct):
         tp = dct['_type_']
         if (not isinstance(tp, str) or
@@ -52,16 +52,15 @@
         return create_array_type(self, other)
 
     def from_param(self, value):
-        return self(value)._as_ffi()
+        if not isinstance(value, _CData):
+            return self(value)
+        return super(SimpleType, self).from_param(value)
 
 class _SimpleCData(_CData):
     __metaclass__ = SimpleType
     _type_ = 'i'
 
     def __init__(self, value=DEFAULT_VALUE):
-        #if address is not DEFAULT_VALUE:
-        #    self._array = ffiarray.fromaddress(address, 1)
-        #else:
         self._array = self._ffiarray(1)
         if value is not DEFAULT_VALUE:
             self._array[0] = value
@@ -70,14 +69,15 @@
         return self._array[0]
 
     def _setvalue(self, value):
-        self._array[0] = value
+        # XXX
+        if isinstance(value, _SimpleCData):
+            self._array[0] = value.value
+        else:
+            self._array[0] = value
     value = property(_getvalue, _setvalue)
 
     def __ctypes_from_outparam__(self):
         return self._array[0]
 
-    def _as_ffi(self):        
-        return CArgObject(self._type_, self.value, type(self))
-
     def __repr__(self):
         return "%s(%s)" % (type(self).__name__, self.value)

Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py	Sun Jan 13 23:26:40 2008
@@ -1,7 +1,7 @@
 
-from _ctypes.basics import _CData
+from _ctypes.basics import _CData, _CDataMeta
 
-class StructureMeta(type):
+class StructureMeta(_CDataMeta):
     def __new__(self, name, cls, typedict):
         return type.__new__(self, name, cls, typedict)
 



More information about the Pypy-commit mailing list