[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