[pypy-svn] r47473 - in pypy/dist/pypy/module/_ffi: . test
fijal at codespeak.net
fijal at codespeak.net
Mon Oct 15 19:12:45 CEST 2007
Author: fijal
Date: Mon Oct 15 19:12:44 2007
New Revision: 47473
Added:
pypy/dist/pypy/module/_ffi/structure.py (contents, props changed)
pypy/dist/pypy/module/_ffi/test/test_struct.py (contents, props changed)
Modified:
pypy/dist/pypy/module/_ffi/__init__.py
pypy/dist/pypy/module/_ffi/app_ffi.py
pypy/dist/pypy/module/_ffi/interp_ffi.py
pypy/dist/pypy/module/_ffi/test/test__ffi.py
Log:
Another approach to structures. This should scale to nested structures,
not rpython by now (will fix it later)
Modified: pypy/dist/pypy/module/_ffi/__init__.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/__init__.py (original)
+++ pypy/dist/pypy/module/_ffi/__init__.py Mon Oct 15 19:12:44 2007
@@ -10,11 +10,11 @@
applevelname = '_ffi'
interpleveldefs = {
- 'CDLL' : 'interp_ffi.W_CDLL',
- 'FuncPtr' : 'interp_ffi.W_FuncPtr',
+ 'CDLL' : 'interp_ffi.W_CDLL',
+ 'FuncPtr' : 'interp_ffi.W_FuncPtr',
+ 'StructureInstance' : 'structure.W_StructureInstance',
}
appleveldefs = {
'Structure' : 'app_ffi.Structure',
- 'StructureInstance' : 'app_ffi.StructureInstance',
}
Modified: pypy/dist/pypy/module/_ffi/app_ffi.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/app_ffi.py (original)
+++ pypy/dist/pypy/module/_ffi/app_ffi.py Mon Oct 15 19:12:44 2007
@@ -6,21 +6,4 @@
def __call__(self, **kwds):
from _ffi import StructureInstance
- return StructureInstance(self.fields, kwds)
-
-class StructureInstance(object):
- def __init__(self, shape, **kwds):
- self.shape = shape
- self.format = "".join([i[1] for i in shape])
- for kwd, value in kwds.items():
- setattr(self, kwd, value)
-
- def pack(self):
- args = [getattr(self, i[0], 0) for i in self.shape]
- return struct.pack(self.format, *args)
-
- def unpack(self, s):
- values = struct.unpack(self.format, s)
- for (name, _), value in zip(self.shape, values):
- setattr(self, name, value)
-
+ return StructureInstance(self, kwds)
Modified: pypy/dist/pypy/module/_ffi/interp_ffi.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/interp_ffi.py (original)
+++ pypy/dist/pypy/module/_ffi/interp_ffi.py Mon Oct 15 19:12:44 2007
@@ -122,7 +122,7 @@
ptr.push_arg(ll_str)
return ll_str
-def push_arg(space, ptr, argnum, argtype, w_arg, to_free, to_reconsider):
+def push_arg(space, ptr, argnum, argtype, w_arg, to_free):
w = space.wrap
# XXX how to handle LONGLONG here?
# they're probably long, so we'll not get them through int_w
@@ -142,11 +142,8 @@
mod = space.getbuiltinmodule('_ffi')
w_StructureInstance = space.getattr(mod, w('StructureInstance'))
if space.is_true(space.isinstance(w_arg, w_StructureInstance)):
- w_pack = space.getattr(w_arg, w('pack'))
- w_res = space.call(w_pack, space.newtuple([]))
- size = space.int_w(space.len(w_res))
- ll_ptr = pack_pointer(space, w_res, ptr)
- to_reconsider.append((argnum, ll_ptr, size))
+ #ptr.push_arg(lltype.cast_int_to_ptr(rffi.VOIDP, space.int_w(space.getattr(w_arg, w('buffer')))))
+ ptr.push_arg(w_arg.ll_buffer)
else:
raise OperationError(space.w_TypeError, w(
"Expected structure, array or simple type"))
@@ -158,11 +155,20 @@
ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items())
-def repack_struct(space, w_struct, value, size):
- w_unpack = space.getattr(w_struct, space.wrap('unpack'))
- # ARGH! too much copying!
- x = "".join([value[i] for i in range(size)])
- space.call(w_unpack, space.newtuple([space.wrap(x)]))
+def wrap_result(space, restype, func):
+ for c, ll_type in ll_typemap_iter:
+ if restype == c:
+ if c == 's' or c == 'p':
+ return space.wrap(rffi.charp2str(func(rffi.CCHARP)))
+ elif c == 'P':
+ res = func(rffi.VOIDP)
+ return space.wrap(lltype.cast_ptr_to_int(res))
+ elif c == 'q' or c == 'Q' or c == 'L':
+ return space.newlong(func(ll_type))
+ else:
+ return space.wrap(func(ll_type))
+ return space.w_None
+wrap_result._annspecialcase_ = 'specialize:arg(2)'
class W_FuncPtr(Wrappable):
def __init__(self, ptr, argtypes, restype):
@@ -177,29 +183,15 @@
raise OperationError(space.w_TypeError, space.wrap(
"Provided keyword arguments for C function call"))
to_free = []
- to_reconsider = []
i = 0
for argtype, w_arg in zip(self.argtypes, args_w):
- push_arg(space, self.ptr, i, argtype, w_arg, to_free, to_reconsider)
+ push_arg(space, self.ptr, i, argtype, w_arg, to_free)
i += 1
try:
- for c, ll_type in ll_typemap_iter:
- if self.restype == c:
- if c == 's' or c == 'p':
- return space.wrap(rffi.charp2str(self.ptr.call(rffi.CCHARP)))
- elif c == 'P':
- res = self.ptr.call(rffi.VOIDP)
- return space.wrap(lltype.cast_ptr_to_int(res))
- elif c == 'q' or c == 'Q' or c == 'L':
- return space.newlong(self.ptr.call(ll_type))
- else:
- return space.wrap(self.ptr.call(ll_type))
+ return wrap_result(space, self.restype, self.ptr.call)
finally:
for elem in to_free:
lltype.free(elem, flavor='raw')
- for num, value, size in to_reconsider:
- repack_struct(space, args_w[num], value, size)
- lltype.free(value, flavor='raw')
call.unwrap_spec = ['self', ObjSpace, Arguments]
W_FuncPtr.typedef = TypeDef(
Added: pypy/dist/pypy/module/_ffi/structure.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/_ffi/structure.py Mon Oct 15 19:12:44 2007
@@ -0,0 +1,83 @@
+
+""" Interpreter-level implementation of structure, exposing ll-structure
+to app-level with apropriate interface
+"""
+
+from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable,\
+ Arguments
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.interpreter.error import OperationError, wrap_oserror
+# XXX we've got the very same info in two places - one is native_fmttable
+# the other one is in rlib/libffi, we should refactor it to reuse the same
+# logic, I'll not touch it by now, and refactor it later
+from pypy.module.struct.nativefmttable import native_fmttable
+from pypy.module._ffi.interp_ffi import wrap_result
+
+def unpack_fields(space, w_fields):
+ fields_w = space.unpackiterable(w_fields)
+ fields = []
+ for w_tup in fields_w:
+ l_w = space.unpackiterable(w_tup)
+ if not len(l_w) == 2:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "Expected list of 2-size tuples"))
+ fields.append((space.str_w(l_w[0]), space.str_w(l_w[1])))
+ return fields
+
+def size_and_pos(fields):
+ size = native_fmttable[fields[0][1]]['size']
+ pos = [0]
+ for i in range(1, len(fields)):
+ field_desc = native_fmttable[fields[i][1]]
+ missing = size % field_desc.get('alignment', 1)
+ if missing:
+ size += field_desc['alignment'] - missing
+ pos.append(size)
+ size += field_desc['size']
+ return size, pos
+
+class W_StructureInstance(Wrappable):
+ def __init__(self, space, w_shape, w_fieldinits):
+ if space.is_true(w_fieldinits):
+ raise OperationError(space.w_ValueError, space.wrap(
+ "Fields should be not initialized with values by now"))
+ w_fields = space.getattr(w_shape, space.wrap('fields'))
+ fields = unpack_fields(space, w_fields)
+ size, pos = size_and_pos(fields)
+ self.fields = fields
+ self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
+ zero=True)
+ self.ll_positions = pos
+ self.next_pos = 0
+
+ def cast_pos(self, ll_t):
+ i = self.next_pos
+ pos = rffi.ptradd(self.ll_buffer, self.ll_positions[i])
+ TP = rffi.CArrayPtr(ll_t)
+ return rffi.cast(TP, pos)[0]
+ cast_pos._annspecialcase_ = 'specialize:arg(1)'
+
+ def getattr(self, space, attr):
+ for i in range(len(self.fields)):
+ name, c = self.fields[i]
+ if name == attr:
+ # XXX RPython-trick for passing lambda around
+ self.next_pos = i
+ return wrap_result(space, c, self.cast_pos)
+ raise OperationError(space.w_AttributeError, space.wrap(
+ "C Structure has no attribute %s" % name))
+ getattr.unwrap_spec = ['self', ObjSpace, str]
+
+ def __del__(self):
+ lltype.free(self.ll_buffer, flavor='raw')
+
+def descr_new_structure_instance(space, w_type, w_shape, w_fieldinits):
+ return W_StructureInstance(space, w_shape, w_fieldinits)
+
+W_StructureInstance.typedef = TypeDef(
+ 'StructureInstance',
+ __new__ = interp2app(descr_new_structure_instance),
+ __getattr__ = interp2app(W_StructureInstance.getattr),
+)
Modified: pypy/dist/pypy/module/_ffi/test/test__ffi.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/test/test__ffi.py (original)
+++ pypy/dist/pypy/module/_ffi/test/test__ffi.py Mon Oct 15 19:12:44 2007
@@ -73,4 +73,7 @@
struct2 = struct_type()
assert gettimeofday(struct2, None) == 0
assert structure.tv_usec != struct2.tv_usec
- assert structure.tv_sec == struct2.tv_sec or structure.tv_sec == struct2.tv_sec - 1
+ assert (structure.tv_sec == struct2.tv_sec) or (structure.tv_sec == struct2.tv_sec - 1)
+ raises(AttributeError, "structure.xxx")
+
+
Added: pypy/dist/pypy/module/_ffi/test/test_struct.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/_ffi/test/test_struct.py Mon Oct 15 19:12:44 2007
@@ -0,0 +1,15 @@
+
+from pypy.module._ffi.structure import sizeof
+
+def unpack(desc):
+ return [('x', i) for i in desc]
+
+def test_sizeof():
+ s_c = sizeof(unpack('c'))
+ s_l = sizeof(unpack('l'))
+ s_q = sizeof(unpack('q'))
+ assert sizeof(unpack('cl')) == 2*s_l
+ assert sizeof(unpack('cq')) == s_q + s_l
+ assert sizeof(unpack('ccq')) == s_q + s_l
+ assert sizeof(unpack('ccccq')) == 4 * s_c + s_q
+
More information about the Pypy-commit
mailing list