[pypy-commit] pypy ffi-backend: Intermediate check-in

arigo noreply at buildbot.pypy.org
Wed Jun 27 10:56:34 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r55856:74705da2923d
Date: 2012-06-27 10:51 +0200
http://bitbucket.org/pypy/pypy/changeset/74705da2923d/

Log:	Intermediate check-in

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
@@ -154,25 +154,15 @@
         self.getcfield(w_attr).write(self._cdata, w_value)
         keepalive_until_here(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 call(self, args_w):
+        w_result = self.ctype.call(self._cdata, args_w)
+        keepalive_until_here(self)
+        return w_result
 
     def write_raw_integer_data(self, source):
         misc.write_raw_integer_data(self._cdata, source, self.ctype.size)
         keepalive_until_here(self)
 
-##    def read_raw_float_data(self):
-##        result = misc.read_raw_float_data(self._cdata, self.ctype.size)
-##        keepalive_until_here(self)
-##        return result
-
     def write_raw_float_data(self, source):
         misc.write_raw_float_data(self._cdata, source, self.ctype.size)
         keepalive_until_here(self)
@@ -235,6 +225,7 @@
     __sub__ = interp2app(W_CData.sub),
     __getattr__ = interp2app(W_CData.getattr),
     __setattr__ = interp2app(W_CData.setattr),
+    __call__ = interp2app(W_CData.call),
 )
 
 W_CData.typedef = TypeDef(
diff --git a/pypy/module/_ffi_backend/ctypefunc.py b/pypy/module/_ffi_backend/ctypefunc.py
--- a/pypy/module/_ffi_backend/ctypefunc.py
+++ b/pypy/module/_ffi_backend/ctypefunc.py
@@ -2,12 +2,31 @@
 Function pointers.
 """
 
+from pypy.rpython.lltypesystem import rffi
+from pypy.rlib import clibffi
+
 from pypy.module._ffi_backend.ctypeptr import W_CTypePtrBase
 
 
 class W_CTypeFunc(W_CTypePtrBase):
 
     def __init__(self, space, fargs, fresult, ellipsis):
+        extra = self._compute_extra_text(fargs, fresult, ellipsis)
+        size = rffi.sizeof(rffi.VOIDP)
+        W_CTypePtrBase.__init__(self, space, size, extra, 2, fresult,
+                                could_cast_anything=False)
+        self.fargs = fargs
+        self.ellipsis = bool(ellipsis)
+        # fresult is stored in self.ctitem
+
+        if not ellipsis:
+            # Functions with '...' varargs are stored without a cif_descr
+            # at all.  The cif is computed on every call from the actual
+            # types passed in.  For all other functions, the cif_descr
+            # is computed here.
+            self.cif_descr = fb_prepare_cif(fargs, fresult)
+
+    def _compute_extra_text(self, fargs, fresult, ellipsis):
         argnames = ['(*)(']
         for i, farg in enumerate(fargs):
             if i > 0:
@@ -18,15 +37,32 @@
                 argnames.append(', ')
             argnames.append('...')
         argnames.append(')')
-        extra = ''.join(argnames)
-        #
-        W_CTypePtrBase.__init__(self, space, extra, 2, fresult)
-        self.can_cast_anything = False
-        self.ellipsis = ellipsis
-        
-        if not ellipsis:
-            # Functions with '...' varargs are stored without a cif_descr
-            # at all.  The cif is computed on every call from the actual
-            # types passed in.  For all other functions, the cif_descr
-            # is computed here.
-            pass
+        return ''.join(argnames)
+
+
+    def call(self, funcaddr, args_w):
+        space = self.space
+        if len(args_w) != len(self.fargs):
+            raise operationerrfmt(space.w_TypeError,
+                                  "'%s' expects %d arguments, got %d",
+                                  self.name, len(self.fargs), len(args_w))
+        xxx
+
+# ____________________________________________________________
+
+
+CIF_DESCRIPTION = lltype.Struct(
+    'CIF_DESCRIPTION',
+    ('cif', clibffi.FFI_CIFP.TO),
+    # the following information is used when doing the call:
+    #  - a buffer of size 'exchange_size' is malloced
+    #  - the arguments are converted from Python objects to raw data
+    #  - the i'th raw data is stored at 'buffer + exchange_offset_arg[1+i]'
+    #  - the call is done
+    #  - the result is read back from 'buffer + exchange_offset_arg[0]'
+    ('exchange_size', lltype.Signed),
+    ('exchange_offset_arg', lltype.Array(lltype.Signed)))
+
+
+def fb_prepare_cif(fargs, fresult):
+    ...
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
@@ -113,6 +113,11 @@
     def _getfields(self):
         return None
 
+    def call(self, funcaddr, args_w):
+        space = self.space
+        raise operationerrfmt(space.w_TypeError,
+                              "cdata '%s' is not callable", ctype.name)
+
 
 W_CType.typedef = TypeDef(
     '_ffi_backend.CTypeDescr',
diff --git a/pypy/module/_ffi_backend/ctypeptr.py b/pypy/module/_ffi_backend/ctypeptr.py
--- a/pypy/module/_ffi_backend/ctypeptr.py
+++ b/pypy/module/_ffi_backend/ctypeptr.py
@@ -13,7 +13,8 @@
 
 class W_CTypePtrOrArray(W_CType):
 
-    def __init__(self, space, size, extra, extra_position, ctitem):
+    def __init__(self, space, size, extra, extra_position, ctitem,
+                 could_cast_anything=True):
         name, name_position = ctitem.insert_name(extra, extra_position)
         W_CType.__init__(self, space, size, name, name_position)
         # this is the "underlying type":
@@ -21,18 +22,12 @@
         #  - for arrays, it is the array item type
         #  - for functions, it is the return type
         self.ctitem = ctitem
-        # overridden to False in W_CTypeFunc
-        self.can_cast_anything = ctitem.cast_anything
+        self.can_cast_anything = could_cast_anything and ctitem.cast_anything
 
 
 class W_CTypePtrBase(W_CTypePtrOrArray):
     # base class for both pointers and pointers-to-functions
 
-    def __init__(self, space, extra, extra_position, ctitem):
-        size = rffi.sizeof(rffi.VOIDP)
-        W_CTypePtrOrArray.__init__(self, space, size,
-                                   extra, extra_position, ctitem)
-
     def cast(self, w_ob):
         space = self.space
         ob = space.interpclass_w(w_ob)
@@ -72,11 +67,12 @@
 
     def __init__(self, space, ctitem):
         from pypy.module._ffi_backend import ctypearray
+        size = rffi.sizeof(rffi.VOIDP)
         if isinstance(ctitem, ctypearray.W_CTypeArray):
             extra = "(*)"    # obscure case: see test_array_add
         else:
             extra = " *"
-        W_CTypePtrBase.__init__(self, space, extra, 2, ctitem)
+        W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
 
     def str(self, cdataobj):
         if isinstance(self.ctitem, W_CTypePrimitiveChar):
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
@@ -5,7 +5,6 @@
 
 from pypy.module._ffi_backend import ctypeobj, ctypeprim, ctypeptr, ctypearray
 from pypy.module._ffi_backend import ctypestruct, ctypevoid, ctypeenum
-from pypy.module._ffi_backend import ctypefunc
 
 
 def alignment(TYPE):
@@ -206,6 +205,7 @@
 
 @unwrap_spec(fresult=ctypeobj.W_CType, ellipsis=int)
 def new_function_type(space, w_fargs, fresult, ellipsis=0):
+    from pypy.module._ffi_backend import ctypefunc
     fargs = []
     for w_farg in space.fixedview(w_fargs):
         farg = space.interpclass_w(w_farg)
diff --git a/pypy/module/_ffi_backend/test/test_c.py b/pypy/module/_ffi_backend/test/test_c.py
--- a/pypy/module/_ffi_backend/test/test_c.py
+++ b/pypy/module/_ffi_backend/test/test_c.py
@@ -3,7 +3,7 @@
 This file is OBSCURE.  Really.  The purpose is to avoid copying and changing
 'test_c.py' from cffi/c/.
 """
-import py
+import py, ctypes
 from pypy.tool.udir import udir
 from pypy.conftest import gettestobjspace
 from pypy.interpreter import gateway
@@ -17,19 +17,42 @@
     def setup_class(cls):
         space = gettestobjspace(usemodules=('_ffi_backend',))
         cls.space = space
+        testfuncs_w = []
+        keepalive_funcs = []
+
         def find_and_load_library_for_test(space, w_name):
             import ctypes.util
             path = ctypes.util.find_library(space.str_w(w_name))
             return space.appexec([space.wrap(path)], """(path):
                 import _ffi_backend
                 return _ffi_backend.load_library(path)""")
+
+        def testfunc0(a, b):
+            return chr(ord(a) + ord(b))
+
+        def prepfunc(func, argtypes, restype):
+            c_func = ctypes.CFUNCTYPE(restype, *argtypes)(func)
+            keepalive_funcs.append(c_func)
+            return ctypes.cast(c_func, ctypes.c_void_p).value
+
+        def testfunc_for_test(space, w_num):
+            if not testfuncs_w:
+                testfuncs = [
+                    prepfunc(testfunc0,
+                             (ctypes.c_char, ctypes.c_char), ctypes.c_char),
+                    ]
+                testfuncs_w[:] = [space.wrap(addr) for addr in testfuncs]
+            return testfuncs_w[space.int_w(w_num)]
+
         w_func = space.wrap(gateway.interp2app(find_and_load_library_for_test))
-        space.appexec([space.wrap(str(tmpdir)), w_func],
-        """(path, func):
+        w_testfunc = space.wrap(gateway.interp2app(testfunc_for_test))
+        space.appexec([space.wrap(str(tmpdir)), w_func, w_testfunc],
+        """(path, func, testfunc):
             import sys
             sys.path.append(path)
             import _all_test_c
             _all_test_c.find_and_load_library = func
+            _all_test_c._testfunc = testfunc
         """)
 
 


More information about the pypy-commit mailing list