[pypy-svn] r50583 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test
arigo at codespeak.net
arigo at codespeak.net
Mon Jan 14 13:06:16 CET 2008
Author: arigo
Date: Mon Jan 14 13:06:16 2008
New Revision: 50583
Modified:
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py
Log:
(fijal, arigo)
A first passing test in _rawffi! :-)
Basically, _rawffi function pointers can only be called
with arguments that are _array's of length 1.
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Mon Jan 14 13:06:16 2008
@@ -9,7 +9,8 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.interpreter.error import OperationError, wrap_oserror
-from pypy.module._rawffi.structure import segfault_exception
+from pypy.module._rawffi.interp_rawffi import segfault_exception
+from pypy.module._rawffi.interp_rawffi import W_DataInstance
from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value, _get_type,\
TYPEMAP
from pypy.rlib.rarithmetic import intmask
@@ -31,79 +32,83 @@
self.of = of
self.itemsize = intmask(TYPEMAP[of].c_size)
- def descr_call(self, space, w_length_or_iterable):
- if space.is_true(space.isinstance(w_length_or_iterable, space.w_int)):
- length = space.int_w(w_length_or_iterable)
- return space.wrap(W_ArrayInstance(space, self, length))
- else:
- items_w = space.unpackiterable(w_length_or_iterable)
- length = len(items_w)
- result = W_ArrayInstance(space, self, length)
- for num in range(len(items_w)):
+ def allocate(self, space, length):
+ return W_ArrayInstance(space, self, length)
+
+ def descr_call(self, space, length, w_iterable=None):
+ result = self.allocate(space, length)
+ if not space.is_w(w_iterable, space.w_None):
+ items_w = space.unpackiterable(w_iterable)
+ iterlength = len(items_w)
+ if iterlength > length:
+ raise OperationError(space.w_ValueError,
+ space.wrap("too many items for specified"
+ " array length"))
+ for num in range(iterlength):
w_item = items_w[num]
- unwrap_value(space, push_elem, result.ll_array, num, self.of,
- w_item, None)
- return space.wrap(result)
+ unwrap_value(space, push_elem, result.ll_buffer, num, self.of,
+ w_item)
+ return space.wrap(result)
def fromaddress(self, space, address, length):
return space.wrap(W_ArrayInstance(space, self, length, address))
fromaddress.unwrap_spec = ['self', ObjSpace, int, int]
+class ArrayCache:
+ def __init__(self, space):
+ self.space = space
+ self.cache = {}
+ self.array_of_ptr = self.get_array_type('P')
+
+ def get_array_type(self, of):
+ try:
+ return self.cache[of]
+ except KeyError:
+ _get_type(self.space, of)
+ result = W_Array(self.space, of)
+ self.cache[of] = result
+ return result
+
+def get_array_cache(space):
+ return space.fromcache(ArrayCache)
+
def descr_new_array(space, w_type, of):
- _get_type(space, of)
- return space.wrap(W_Array(space, of))
+ array_type = get_array_cache(space).get_array_type(of)
+ return space.wrap(array_type)
W_Array.typedef = TypeDef(
'Array',
__new__ = interp2app(descr_new_array, unwrap_spec=[ObjSpace, W_Root, str]),
__call__ = interp2app(W_Array.descr_call,
- unwrap_spec=['self', ObjSpace, W_Root]),
+ unwrap_spec=['self', ObjSpace, int, W_Root]),
fromaddress = interp2app(W_Array.fromaddress),
of = interp_attrproperty('of', W_Array),
)
W_Array.typedef.acceptable_as_base_class = False
-class W_ArrayInstance(Wrappable):
+class W_ArrayInstance(W_DataInstance):
def __init__(self, space, shape, length, address=0):
- self.ll_array = lltype.nullptr(rffi.VOIDP.TO)
- self.alloced = False
+ W_DataInstance.__init__(self, space, shape.itemsize * length, address)
self.length = length
self.shape = shape
- if address != 0:
- self.ll_array = rffi.cast(rffi.VOIDP, address)
- else:
- size = shape.itemsize * length
- self.ll_array = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
- zero=True)
-
# XXX don't allow negative indexes, nor slices
def setitem(self, space, num, w_value):
if num >= self.length or num < 0:
raise OperationError(space.w_IndexError, space.w_None)
- unwrap_value(space, push_elem, self.ll_array, num, self.shape.of, w_value,
- None)
+ unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.of,
+ w_value)
setitem.unwrap_spec = ['self', ObjSpace, int, W_Root]
def getitem(self, space, num):
if num >= self.length or num < 0:
raise OperationError(space.w_ValueError, space.wrap(
"Getting element %d of array sized %d" % (num, self.length)))
- return wrap_value(space, get_elem, self.ll_array, num, self.shape.of)
+ return wrap_value(space, get_elem, self.ll_buffer, num, self.shape.of)
getitem.unwrap_spec = ['self', ObjSpace, int]
- def getbuffer(space, self):
- return space.wrap(rffi.cast(rffi.INT, self.ll_array))
-
- def free(self, space):
- if not self.ll_array:
- raise segfault_exception(space, "freeing NULL pointer")
- lltype.free(self.ll_array, flavor='raw')
- self.ll_array = lltype.nullptr(rffi.VOIDP.TO)
- free.unwrap_spec = ['self', ObjSpace]
-
W_ArrayInstance.typedef = TypeDef(
'ArrayInstance',
__setitem__ = interp2app(W_ArrayInstance.setitem),
@@ -111,6 +116,6 @@
buffer = GetSetProperty(W_ArrayInstance.getbuffer),
shape = interp_attrproperty('shape', W_ArrayInstance),
free = interp2app(W_ArrayInstance.free),
+ byptr = interp2app(W_ArrayInstance.byptr),
)
-
-
+W_ArrayInstance.typedef.acceptable_as_base_class = False
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Mon Jan 14 13:06:16 2008
@@ -52,6 +52,7 @@
'z' : ffi_type_pointer,
'O' : ffi_type_pointer,
}
+TYPEMAP_PTR_LETTERS = "POsz"
LL_TYPEMAP = {
'c' : rffi.CHAR,
@@ -122,8 +123,8 @@
argtypes = [space.str_w(w_arg) for w_arg in argtypes_w]
ffi_argtypes = [self.get_type(arg) for arg in argtypes]
try:
- ptr = self.cdll.getpointer(name, ffi_argtypes, ffi_restype)
- w_funcptr = W_FuncPtr(ptr, argtypes, restype)
+ ptr = self.cdll.getrawpointer(name, ffi_argtypes, ffi_restype)
+ w_funcptr = W_FuncPtr(space, ptr, argtypes, restype)
space.setitem(self.w_cache, w_key, w_funcptr)
return w_funcptr
except KeyError:
@@ -190,45 +191,53 @@
SIZE_CHECKERS[c] = make_size_checker(c, native_fmttable[c]['size'], signed)
unroll_size_checkers = unrolling_iterable(SIZE_CHECKERS.items())
-def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg, to_free):
- w = space.wrap
- if tp == "d" or tp == "f":
- if tp == "d":
- push_func(add_arg, argdesc, space.float_w(w_arg))
+def segfault_exception(space, reason):
+ w_mod = space.getbuiltinmodule("_rawffi")
+ w_exception = space.getattr(w_mod, space.wrap("SegfaultException"))
+ return OperationError(w_exception, space.wrap(reason))
+
+
+class W_DataInstance(Wrappable):
+ def __init__(self, space, size, address=0):
+ if address != 0:
+ self.ll_buffer = rffi.cast(rffi.VOIDP, address)
else:
- push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT,
- space.float_w(w_arg)))
- elif tp == "s" or tp =="z":
- ll_str = rffi.str2charp(space.str_w(w_arg))
- if to_free is not None:
- to_free.append(ll_str)
- push_func(add_arg, argdesc, ll_str)
- elif tp == "P" or tp == "O":
+ self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
+ zero=True)
+
+ def getbuffer(space, self):
+ return space.wrap(rffi.cast(rffi.INT, self.ll_buffer))
+
+ def byptr(self, space):
+ from pypy.module._rawffi.array import get_array_cache
+ array_of_ptr = get_array_cache(space).array_of_ptr
+ array = array_of_ptr.allocate(space, 1)
+ array.setitem(space, 0, space.wrap(self))
+ return space.wrap(array)
+ byptr.unwrap_spec = ['self', ObjSpace]
+
+ def free(self, space):
+ if not self.ll_buffer:
+ raise segfault_exception(space, "freeing NULL pointer")
+ lltype.free(self.ll_buffer, flavor='raw')
+ self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO)
+ free.unwrap_spec = ['self', ObjSpace]
+
+
+def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg):
+ w = space.wrap
+ if tp == "d":
+ push_func(add_arg, argdesc, space.float_w(w_arg))
+ elif tp == "f":
+ push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT,
+ space.float_w(w_arg)))
+ elif tp in TYPEMAP_PTR_LETTERS:
# check for NULL ptr
- if space.is_w(w_arg, space.w_None):
- push_func(add_arg, argdesc, lltype.nullptr(rffi.VOIDP.TO))
- elif space.is_true(space.isinstance(w_arg, space.w_int)):
+ if space.is_true(space.isinstance(w_arg, space.w_int)):
push_func(add_arg, argdesc, rffi.cast(rffi.VOIDP, space.int_w(w_arg)))
- elif space.is_true(space.isinstance(w_arg, space.w_basestring)):
- if to_free is not None:
- to_free.append(pack_pointer(space, add_arg, argdesc, w_arg, push_func))
else:
- mod = space.getbuiltinmodule('_rawffi')
- w_StructureInstance = space.getattr(mod, w('StructureInstance'))
- w_ArrayInstance = space.getattr(mod, w('ArrayInstance'))
- #w_CallbackPtr = space.getattr(mod, w('CallbackPtr'))
- if space.is_true(space.isinstance(w_arg, w_StructureInstance)) or\
- space.is_true(space.isinstance(w_arg, w_ArrayInstance)):
- ptr = rffi.cast(rffi.VOIDP, space.int_w(space.getattr(w_arg, w('buffer'))))
- push_func(add_arg, argdesc, ptr)
- #elif space.is_true(space.isinstance(w_arg, w_CallbackPtr)):
- # TP = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
- # ptr = rffi.cast(TP, space.int_w(space.getattr(w_arg, w('buffer'))))
- # push_func(add_arg, argdesc, ptr)
-
- else:
- raise OperationError(space.w_TypeError, w(
- "Expected structure, array or simple type"))
+ datainstance = space.interp_w(W_DataInstance, w_arg)
+ push_func(add_arg, argdesc, datainstance.ll_buffer)
elif tp == "c":
s = space.str_w(w_arg)
if len(s) != 1:
@@ -298,30 +307,35 @@
push._annspecialcase_ = 'specialize:argtype(2)'
class W_FuncPtr(Wrappable):
- def __init__(self, ptr, argtypes, restype):
+ def __init__(self, space, ptr, argtypes, restype):
+ from pypy.module._rawffi.array import get_array_cache
self.ptr = ptr
- self.restype = restype
+ cache = get_array_cache(space)
+ self.resarray = cache.get_array_type(restype)
self.argtypes = argtypes
- def call(self, space, arguments):
- args_w, kwds_w = arguments.unpack()
- # C has no keyword arguments
- if kwds_w:
- raise OperationError(space.w_TypeError, space.wrap(
- "Provided keyword arguments for C function call"))
- to_free = []
- i = 0
- for i in range(len(self.argtypes)):
+ def call(self, space, args_w):
+ from pypy.module._rawffi.array import W_ArrayInstance
+ argnum = len(args_w)
+ if argnum != len(self.argtypes):
+ msg = "Wrong number of argument: expected %d, got %d" % (
+ len(self.argtypes), argnum)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ args_ll = []
+ for i in range(argnum):
argtype = self.argtypes[i]
w_arg = args_w[i]
- unwrap_value(space, push, self.ptr, i, argtype, w_arg, to_free)
- i += 1
- try:
- return wrap_value(space, ptr_call, self.ptr, None, self.restype)
- finally:
- for elem in to_free:
- lltype.free(elem, flavor='raw')
- call.unwrap_spec = ['self', ObjSpace, Arguments]
+ arg = space.interp_w(W_ArrayInstance, w_arg)
+ if arg.shape.of != argtype:
+ msg = "Argument %d should be typecode %s, got %s" % (
+ i+1, argtype, arg.shape.of)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ args_ll.append(arg.ll_buffer)
+ # XXX we could avoid the intermediate list args_ll
+ result = self.resarray.allocate(space, 1)
+ self.ptr.call(args_ll, result.ll_buffer)
+ return space.wrap(result)
+ call.unwrap_spec = ['self', ObjSpace, 'args_w']
W_FuncPtr.typedef = TypeDef(
'FuncPtr',
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Mon Jan 14 13:06:16 2008
@@ -10,6 +10,8 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.interpreter.error import OperationError, wrap_oserror
+from pypy.module._rawffi.interp_rawffi import segfault_exception
+from pypy.module._rawffi.interp_rawffi import W_DataInstance
from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value, _get_type,\
TYPEMAP
from pypy.rlib.rarithmetic import intmask
@@ -96,20 +98,10 @@
return rffi.cast(TP, pos)[0]
cast_pos._annspecialcase_ = 'specialize:arg(2)'
-def segfault_exception(space, reason):
- w_mod = space.getbuiltinmodule("_rawffi")
- w_exception = space.getattr(w_mod, space.wrap("SegfaultException"))
- return OperationError(w_exception, space.wrap(reason))
-
-class W_StructureInstance(Wrappable):
+class W_StructureInstance(W_DataInstance):
def __init__(self, space, shape, address, fieldinits_w):
- self.free_afterwards = False
+ W_DataInstance.__init__(self, space, shape.size, address)
self.shape = shape
- if address != 0:
- self.ll_buffer = rffi.cast(rffi.VOIDP, address)
- else:
- self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, shape.size, flavor='raw',
- zero=True)
if fieldinits_w:
for field, w_value in fieldinits_w.iteritems():
self.setattr(space, field, w_value)
@@ -138,16 +130,6 @@
unwrap_value(space, push_field, self, i, c, w_value, None)
setattr.unwrap_spec = ['self', ObjSpace, str, W_Root]
- def free(self, space):
- if not self.ll_buffer:
- raise segfault_exception(space, "freeing NULL pointer")
- lltype.free(self.ll_buffer, flavor='raw')
- self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO)
- free.unwrap_spec = ['self', ObjSpace]
-
- def getbuffer(space, self):
- return space.wrap(rffi.cast(rffi.INT, self.ll_buffer))
-
W_StructureInstance.typedef = TypeDef(
'StructureInstance',
@@ -156,6 +138,7 @@
buffer = GetSetProperty(W_StructureInstance.getbuffer),
free = interp2app(W_StructureInstance.free),
shape = interp_attrproperty('shape', W_StructureInstance),
+ byptr = interp2app(W_StructureInstance.byptr),
)
W_StructureInstance.typedef.acceptable_as_base_class = False
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Mon Jan 14 13:06:16 2008
@@ -131,13 +131,20 @@
def test_getchar(self):
import _rawffi
lib = _rawffi.CDLL(self.lib_name)
- get_char = lib.ptr('get_char', ['s', 'H'], 'c')
- assert get_char('dupa', 2) == 'p'
- assert get_char('dupa', 1) == 'u'
- raises(ValueError, "get_char('xxx', 2 ** 17)")
- raises(ValueError, "get_char('xxx', -1)")
- get_char = lib.ptr('get_char', ['z', 'H'], 'c')
- assert get_char('dupa', 2) == 'p'
+ get_char = lib.ptr('get_char', ['P', 'H'], 'c')
+ A = _rawffi.Array('c')
+ B = _rawffi.Array('H')
+ dupa = A(5, 'dupa')
+ dupaptr = dupa.byptr()
+ for i in range(4):
+ intptr = B(1)
+ intptr[0] = i
+ res = get_char(dupaptr, intptr)
+ assert res[0] == 'dupa'[i]
+ res.free()
+ intptr.free()
+ dupaptr.free()
+ dupa.free()
def test_returning_str(self):
import _rawffi
More information about the Pypy-commit
mailing list