[pypy-commit] pypy ffi-backend: Progress...

arigo noreply at buildbot.pypy.org
Wed Jun 20 12:29:12 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r55727:b46e2561f838
Date: 2012-06-19 21:59 +0200
http://bitbucket.org/pypy/pypy/changeset/b46e2561f838/

Log:	Progress...

diff --git a/pypy/module/_ffi_backend/cdataobj.py b/pypy/module/_ffi_backend/cdataobj.py
--- a/pypy/module/_ffi_backend/cdataobj.py
+++ b/pypy/module/_ffi_backend/cdataobj.py
@@ -3,9 +3,11 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib import rgc
 
+from pypy.module._ffi_backend import misc
+
 
 class W_CData(Wrappable):
     _immutable_ = True
@@ -22,20 +24,22 @@
     def repr(self):
         return self.space.wrap("<cdata '%s'>" % self.ctype.name)
 
+    def int(self):
+        return self.ctype.int(self)
+
+    def read_raw_signed_data(self):
+        result = misc.read_raw_signed_data(self.cdata, self.ctype.size)
+        keepalive_until_here(self)
+        return result
+
+    def read_raw_unsigned_data(self):
+        result = misc.read_raw_unsigned_data(self.cdata, self.ctype.size)
+        keepalive_until_here(self)
+        return result
+
     def write_raw_integer_data(self, source):
-        size = self.ctype.size
-        for TP, TPP in _prim_unsigned_types:
-            if size == rffi.sizeof(TP):
-                rffi.cast(TPP, self.cdata)[0] = rffi.cast(TP, source)
-                return
-        raise NotImplementedError("bad integer size")
-
-_prim_unsigned_types = unrolling_iterable([
-    (rffi.UCHAR, rffi.UCHARP),
-    (rffi.USHORT, rffi.USHORTP),
-    (rffi.UINT, rffi.UINTP),
-    (rffi.ULONG, rffi.ULONGP),
-    (rffi.ULONGLONG, rffi.ULONGLONGP)])
+        misc.write_raw_integer_data(self.cdata, source, self.ctype.size)
+        keepalive_until_here(self)
 
 
 class W_CDataOwn(W_CData):
@@ -52,6 +56,7 @@
 W_CData.typedef = TypeDef(
     '_ffi_backend.CData',
     __repr__ = interp2app(W_CData.repr),
+    __int__ = interp2app(W_CData.int),
     )
 W_CData.acceptable_as_base_class = False
 
diff --git a/pypy/module/_ffi_backend/ctypeobj.py b/pypy/module/_ffi_backend/ctypeobj.py
--- a/pypy/module/_ffi_backend/ctypeobj.py
+++ b/pypy/module/_ffi_backend/ctypeobj.py
@@ -3,6 +3,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.rarithmetic import intmask
 
 from pypy.module._ffi_backend import cdataobj, misc
 
@@ -22,6 +23,11 @@
     def cast(self, w_ob):
         raise NotImplementedError
 
+    def int(self, cdataobj):
+        space = self.space
+        raise operationerrfmt(space.w_TypeError,
+                              "int() not supported on cdata '%s'", self.name)
+
 
 class W_CTypePrimitive(W_CType):
 
@@ -41,11 +47,27 @@
 
 
 class W_CTypePrimitiveChar(W_CTypePrimitive):
-    pass
+
+    def int(self, cdataobj):
+        xxx
+
 
 class W_CTypePrimitiveSigned(W_CTypePrimitive):
-    pass
 
+    def int(self, cdataobj):
+        if self.value_fits_long:
+            # this case is to handle enums, but also serves as a slight
+            # performance improvement for some other primitive types
+            value = intmask(cdataobj.read_raw_signed_data())
+            return self.space.wrap(value)
+        else:
+            return cdataobj.convert_to_object()
+
+
+class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
+
+    def int(self, cdataobj):
+        return cdataobj.convert_to_object()
 
 
 W_CType.typedef = TypeDef(
diff --git a/pypy/module/_ffi_backend/misc.py b/pypy/module/_ffi_backend/misc.py
--- a/pypy/module/_ffi_backend/misc.py
+++ b/pypy/module/_ffi_backend/misc.py
@@ -1,5 +1,43 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rarithmetic import r_ulonglong
+from pypy.rlib.unroll import unrolling_iterable
+
+# ____________________________________________________________
+
+_prim_signed_types = unrolling_iterable([
+    (rffi.SIGNEDCHAR, rffi.SIGNEDCHARP),
+    (rffi.SHORT, rffi.SHORTP),
+    (rffi.INT, rffi.INTP),
+    (rffi.LONG, rffi.LONGP),
+    (rffi.LONGLONG, rffi.LONGLONGP)])
+
+_prim_unsigned_types = unrolling_iterable([
+    (rffi.UCHAR, rffi.UCHARP),
+    (rffi.USHORT, rffi.USHORTP),
+    (rffi.UINT, rffi.UINTP),
+    (rffi.ULONG, rffi.ULONGP),
+    (rffi.ULONGLONG, rffi.ULONGLONGP)])
+
+def read_raw_signed_data(target, size):
+    for TP, TPP in _prim_signed_types:
+        if size == rffi.sizeof(TP):
+            return rffi.cast(rffi.LONGLONG, rffi.cast(TPP, target)[0])
+    raise NotImplementedError("bad integer size")
+
+def read_raw_unsigned_data(target, size):
+    for TP, TPP in _prim_unsigned_types:
+        if size == rffi.sizeof(TP):
+            return rffi.cast(rffi.ULONGLONG, rffi.cast(TPP, target)[0])
+    raise NotImplementedError("bad integer size")
+
+def write_raw_integer_data(target, source, size):
+    for TP, TPP in _prim_unsigned_types:
+        if size == rffi.sizeof(TP):
+            rffi.cast(TPP, target)[0] = rffi.cast(TP, source)
+            return
+    raise NotImplementedError("bad integer size")
+
+# ____________________________________________________________
 
 
 UNSIGNED = 0x1000
diff --git a/pypy/module/_ffi_backend/newtype.py b/pypy/module/_ffi_backend/newtype.py
--- a/pypy/module/_ffi_backend/newtype.py
+++ b/pypy/module/_ffi_backend/newtype.py
@@ -11,16 +11,27 @@
 PRIMITIVE_TYPES = {}
 
 def eptype(name, TYPE, ctypecls):
-    PRIMITIVE_TYPES[name] = ctypecls, rffi.sizeof(TYPE)
+    size = rffi.sizeof(TYPE)
+    if ctypecls is ctypeobj.W_CTypePrimitiveSigned:
+        value_fits_long = size <= rffi.sizeof(lltype.Signed)
+    elif ctypecls is ctypeobj.W_CTypePrimitiveUnsigned:
+        value_fits_long = size < rffi.sizeof(lltype.Signed)
+    else:
+        value_fits_long = False
+    PRIMITIVE_TYPES[name] = ctypecls, size, value_fits_long
 
-eptype("char", lltype.Char, ctypeobj.W_CTypePrimitiveChar)
+eptype("char",        lltype.Char,     ctypeobj.W_CTypePrimitiveChar)
 eptype("signed char", rffi.SIGNEDCHAR, ctypeobj.W_CTypePrimitiveSigned)
+eptype("short",       rffi.SHORT,      ctypeobj.W_CTypePrimitiveSigned)
+# xxx
 
 
 @unwrap_spec(name=str)
 def new_primitive_type(space, name):
     try:
-        ctypecls, size = PRIMITIVE_TYPES[name]
+        ctypecls, size, value_fits_long = PRIMITIVE_TYPES[name]
     except KeyError:
         raise OperationError(space.w_KeyError, space.wrap(name))
-    return ctypecls(space, name, size)
+    ctype = ctypecls(space, name, size)
+    ctype.value_fits_long = value_fits_long
+    return ctype


More information about the pypy-commit mailing list