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

fijal at codespeak.net fijal at codespeak.net
Thu Jan 10 11:55:04 CET 2008


Author: fijal
Date: Thu Jan 10 11:55:04 2008
New Revision: 50485

Modified:
   pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.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
Log:
Wack enough to make 5 tests of test_pointers pass (no memory clearing yet,
it leaks like hell).


Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py	Thu Jan 10 11:55:04 2008
@@ -4,6 +4,7 @@
 from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr
 from _ctypes.dummy import _cast_addr
 
+from _ctypes.basics import _CData
 from _ctypes.primitive import _SimpleCData, sizeof, alignment, byref
 from _ctypes.pointer import _Pointer
 from _ctypes.function import CFuncPtr

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	Thu Jan 10 11:55:04 2008
@@ -1,6 +1,7 @@
 import _ffi
 
 class CFuncPtrType(type):
+    # XXX write down here defaults and such things
     pass
 
 class CFuncPtr(object):
@@ -21,21 +22,43 @@
             self.dll = None
 
     def __call__(self, *args):
-        assert self.argtypes is not None #XXX for now
-        assert self.restype is not None #XXX for now
-        if len(args) != len(self.argtypes):
-            raise TypeError("%s takes %s arguments, given %s" % (self.name,
-                len(self.argtypes), len(args)))
-        return self._getfuncptr()(*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)))
+        res = self._getfuncptr(args)(*[arg.value for arg in args])
+        if issubclass(self.restype, ctypes._SimpleCData):
+            return res
+        else:
+            # XXX pointers
+            return self.restype(address=res)
 
-    def _getfuncptr(self):
+    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
-        argtps = [argtype._type_ for argtype in self.argtypes]
-        restp = self.restype._type_
+        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 = self.argtypes
         self._restype = self.restype
         return funcptr
+
+    def _guess_magic_args(self, args):
+        import _ctypes
+        res = []
+        for arg in args:
+            if isinstance(arg, _ctypes._CData):
+                res.append(type(arg))
+            else:
+                raise TypeError("Cannot convert %s" % arg)
+        return res

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	Thu Jan 10 11:55:04 2008
@@ -1,30 +1,57 @@
 
 import _ffi
+from _ctypes.basics import _CData
+
+DEFAULT_VALUE = object()
 
 class PointerType(type):
     def __new__(self, name, cls, typedict):
         d = dict(
-            size   = _ffi.sizeof('P'),
-            align  = _ffi.alignment('P'),
-            length = 1
+            size       = _ffi.sizeof('P'),
+            align      = _ffi.alignment('P'),
+            length     = 1,
+            _ffiletter = 'P'
         )
         # XXX check if typedict['_type_'] is any sane
         # XXX remember about paramfunc
         obj = type.__new__(self, name, cls, typedict)
         for k, v in d.iteritems():
             setattr(obj, k, v)
+        if '_type_' in typedict:
+            ffiarray = _ffi.Array(typedict['_type_']._ffiletter)
+            def __init__(self, value=0, address=DEFAULT_VALUE):
+                if address is not DEFAULT_VALUE:
+                    self._array = ffiarray.fromaddress(address, 1)
+                elif value == 0:
+                    # null pointer
+                    self._array = ffiarray.fromaddress(0, 1)
+                else:
+                    self._array = ffiarray.fromaddress(value._array.buffer, 1)
+            obj._ffiarray = ffiarray
+        else:
+            def __init__(self, value=0):
+                raise TypeError("%s has no type" % obj)
+        obj.__init__ = __init__
         return obj
 
-class _Pointer(object):
+class _Pointer(_CData):
     __metaclass__ = PointerType
 
-    def __init__(self, value=None):
-        if value is None:
-            self.is_null = True
-        else:
-            self.value = value
-        # we should later check why exactly this is the case
-        try:
-            type(self).__dict__['_type_']
-        except KeyError:
-            raise TypeError("%s has no _type_" % self.__class__)
+    def getvalue(self):
+        return self._array
+
+    value = property(getvalue)
+
+    def getcontents(self):
+        return self._type_.from_address(self._array.buffer)
+
+    def setcontents(self, value):
+        self._array = self._ffiarray.fromaddress(value._array.buffer, 1)
+
+    def __getitem__(self, item):
+        return self._array[item]
+
+    def __setitem__(self, item, value):
+        self._array[item] = value
+
+    contents = property(getcontents, setcontents)

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	Thu Jan 10 11:55:04 2008
@@ -2,6 +2,8 @@
 
 SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv"
 
+from _ctypes.basics import _CData
+
 class NULL(object):
     pass
 NULL = NULL()
@@ -42,20 +44,27 @@
             raise ValueError('%s is not a type character' % (tp))
         default = TP_TO_DEFAULT[tp]
         ffitp = TP_TO_FFITP.get(tp, tp)
-        ffistruct = _ffi.Structure([("value", ffitp)])
-        def __init__(self, value=DEFAULT_VALUE):
-            self._struct = ffistruct()
-            if value is not DEFAULT_VALUE:
-                self._struct.value = value
+        ffiarray = _ffi.Array(ffitp)
+        def __init__(self, value=DEFAULT_VALUE, address=DEFAULT_VALUE):
+            if address is not DEFAULT_VALUE:
+                self._array = ffiarray.fromaddress(address, 1)
+            else:
+                self._array = ffiarray(1)
+                if value is not DEFAULT_VALUE:
+                    self._array[0] = value
         dct['__init__'] = __init__
         result = type.__new__(self, name, bases, dct)
-        result._ffistruct = ffistruct
+        result._ffiarray = ffiarray
+        result._ffiletter = result._type_
         return result
 
+    def from_address(self, address):
+        return self(address=address)
+
     def __mul__(self, other):
         pass
 
-class _SimpleCData(object):
+class _SimpleCData(_CData):
     __metaclass__ = SimpleType
     _type_ = 'i'
     def from_param(cls, *args, **kwargs):
@@ -63,10 +72,10 @@
     from_param = classmethod(from_param)
 
     def _getvalue(self):
-        return self._struct.value
+        return self._array[0]
 
     def _setvalue(self, val):
-        self._struct.value = value
+        self._array[0] = value
     value = property(_getvalue, _setvalue)
 
     def __repr__(self):



More information about the Pypy-commit mailing list