[pypy-commit] pypy ffi-backend: Fix the new test.
arigo
noreply at buildbot.pypy.org
Mon Jul 30 16:31:16 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r56508:04fd96420368
Date: 2012-07-30 16:30 +0200
http://bitbucket.org/pypy/pypy/changeset/04fd96420368/
Log: Fix the new test.
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -10,7 +10,6 @@
from pypy.rlib.objectmodel import keepalive_until_here
from pypy.rlib.rarithmetic import ovfcheck
-from pypy.module._cffi_backend.ctypeobj import W_CType
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveChar
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveUniChar
from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
@@ -18,8 +17,8 @@
class W_CTypeArray(W_CTypePtrOrArray):
- _attrs_ = ['length', 'ctptr']
- _immutable_fields_ = ['length', 'ctptr']
+ _attrs_ = ['ctptr']
+ _immutable_fields_ = ['ctptr']
def __init__(self, space, ctptr, length, arraysize, extra):
W_CTypePtrOrArray.__init__(self, space, arraysize, extra, 0,
@@ -92,55 +91,7 @@
return self
def convert_from_object(self, cdata, w_ob):
- space = self.space
- if (space.isinstance_w(w_ob, space.w_list) or
- space.isinstance_w(w_ob, space.w_tuple)):
- lst_w = space.listview(w_ob)
- if self.length >= 0 and len(lst_w) > self.length:
- raise operationerrfmt(space.w_IndexError,
- "too many initializers for '%s' (got %d)",
- self.name, len(lst_w))
- ctitem = self.ctitem
- for i in range(len(lst_w)):
- ctitem.convert_from_object(cdata, lst_w[i])
- cdata = rffi.ptradd(cdata, ctitem.size)
- elif isinstance(self.ctitem, W_CTypePrimitiveChar):
- try:
- s = space.str_w(w_ob)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise self._convert_error("str or list or tuple", w_ob)
- n = len(s)
- if self.length >= 0 and n > self.length:
- raise operationerrfmt(space.w_IndexError,
- "initializer string is too long for '%s'"
- " (got %d characters)",
- self.name, n)
- for i in range(n):
- cdata[i] = s[i]
- if n != self.length:
- cdata[n] = '\x00'
- elif isinstance(self.ctitem, W_CTypePrimitiveUniChar):
- try:
- s = space.unicode_w(w_ob)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise self._convert_error("unicode or list or tuple", w_ob)
- n = len(s)
- if self.length >= 0 and n > self.length:
- raise operationerrfmt(space.w_IndexError,
- "initializer unicode string is too long for '%s'"
- " (got %d characters)",
- self.name, n)
- unichardata = rffi.cast(rffi.CWCHARP, cdata)
- for i in range(n):
- unichardata[i] = s[i]
- if n != self.length:
- unichardata[n] = u'\x00'
- else:
- raise self._convert_error("list or tuple", w_ob)
+ self.convert_array_from_object(cdata, w_ob)
def convert_to_object(self, cdata):
return cdataobj.W_CData(self.space, cdata, self)
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -10,7 +10,7 @@
from pypy.rlib.objectmodel import keepalive_until_here
from pypy.module._cffi_backend.ctypeobj import W_CType
-from pypy.module._cffi_backend.ctypeptr import W_CTypePtrBase
+from pypy.module._cffi_backend.ctypeptr import W_CTypePtrBase, W_CTypePointer
from pypy.module._cffi_backend.ctypevoid import W_CTypeVoid
from pypy.module._cffi_backend.ctypestruct import W_CTypeStruct
from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion
@@ -127,38 +127,9 @@
buffer_array[i] = data
w_obj = args_w[i]
argtype = self.fargs[i]
- #
- # special-case for strings. xxx should avoid copying
- if argtype.is_char_ptr_or_array():
- try:
- s = space.str_w(w_obj)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- else:
- raw_string = rffi.str2charp(s)
- rffi.cast(rffi.CCHARPP, data)[0] = raw_string
- # set the "must free" flag to 1
- set_mustfree_flag(data, 1)
- mustfree_max_plus_1 = i + 1
- continue # skip the convert_from_object()
-
- # set the "must free" flag to 0
- set_mustfree_flag(data, 0)
- #
- if argtype.is_unichar_ptr_or_array():
- try:
- space.unicode_w(w_obj)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- else:
- # passing a unicode raises NotImplementedError for now
- raise OperationError(space.w_NotImplementedError,
- space.wrap("automatic unicode-to-"
- "'wchar_t *' conversion"))
- #
- argtype.convert_from_object(data, w_obj)
+ if argtype.convert_argument_from_object(data, w_obj):
+ # argtype is a pointer type, and w_obj a list/tuple/str
+ mustfree_max_plus_1 = i + 1
resultdata = rffi.ptradd(buffer, cif_descr.exchange_result)
ec = cerrno.get_errno_container(space)
@@ -189,7 +160,7 @@
finally:
for i in range(mustfree_max_plus_1):
argtype = self.fargs[i]
- if argtype.is_char_ptr_or_array():
+ if isinstance(argtype, W_CTypePointer):
data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
if get_mustfree_flag(data):
raw_string = rffi.cast(rffi.CCHARPP, data)[0]
@@ -413,7 +384,7 @@
# loop over args
for i, farg in enumerate(self.fargs):
- if farg.is_char_ptr_or_array():
+ if isinstance(farg, W_CTypePointer):
exchange_offset += 1 # for the "must free" flag
exchange_offset = self.align_arg(exchange_offset)
cif_descr.exchange_args[i] = exchange_offset
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -73,6 +73,10 @@
raise operationerrfmt(space.w_TypeError,
"cannot initialize cdata '%s'", self.name)
+ def convert_argument_from_object(self, cdata, w_ob):
+ self.convert_from_object(cdata, w_ob)
+ return False
+
def _convert_error(self, expected, w_got):
space = self.space
ob = space.interpclass_w(w_got)
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -2,17 +2,21 @@
Pointers.
"""
-from pypy.interpreter.error import operationerrfmt
-from pypy.rpython.lltypesystem import rffi
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.objectmodel import keepalive_until_here
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.module._cffi_backend.ctypeobj import W_CType
-from pypy.module._cffi_backend import cdataobj, misc
+from pypy.module._cffi_backend import cdataobj, misc, ctypeprim
class W_CTypePtrOrArray(W_CType):
- _attrs_ = ['ctitem', 'can_cast_anything', 'is_struct_ptr']
- _immutable_fields_ = ['ctitem', 'can_cast_anything', 'is_struct_ptr']
+ _attrs_ = ['ctitem', 'can_cast_anything', 'is_struct_ptr',
+ 'length']
+ _immutable_fields_ = ['ctitem', 'can_cast_anything', 'is_struct_ptr',
+ 'length']
+ length = -1
def __init__(self, space, size, extra, extra_position, ctitem,
could_cast_anything=True):
@@ -28,15 +32,12 @@
self.is_struct_ptr = isinstance(ctitem, W_CTypeStructOrUnion)
def is_char_ptr_or_array(self):
- from pypy.module._cffi_backend import ctypeprim
return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveChar)
def is_unichar_ptr_or_array(self):
- from pypy.module._cffi_backend import ctypeprim
return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar)
def is_char_or_unichar_ptr_or_array(self):
- from pypy.module._cffi_backend import ctypeprim
return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveCharOrUniChar)
def cast(self, w_ob):
@@ -56,6 +57,57 @@
value = rffi.cast(rffi.CCHARP, value)
return cdataobj.W_CData(space, value, self)
+ def convert_array_from_object(self, cdata, w_ob):
+ space = self.space
+ if (space.isinstance_w(w_ob, space.w_list) or
+ space.isinstance_w(w_ob, space.w_tuple)):
+ lst_w = space.listview(w_ob)
+ if self.length >= 0 and len(lst_w) > self.length:
+ raise operationerrfmt(space.w_IndexError,
+ "too many initializers for '%s' (got %d)",
+ self.name, len(lst_w))
+ ctitem = self.ctitem
+ for i in range(len(lst_w)):
+ ctitem.convert_from_object(cdata, lst_w[i])
+ cdata = rffi.ptradd(cdata, ctitem.size)
+ elif isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveChar):
+ try:
+ s = space.str_w(w_ob)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ raise self._convert_error("str or list or tuple", w_ob)
+ n = len(s)
+ if self.length >= 0 and n > self.length:
+ raise operationerrfmt(space.w_IndexError,
+ "initializer string is too long for '%s'"
+ " (got %d characters)",
+ self.name, n)
+ for i in range(n):
+ cdata[i] = s[i]
+ if n != self.length:
+ cdata[n] = '\x00'
+ elif isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar):
+ try:
+ s = space.unicode_w(w_ob)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ raise self._convert_error("unicode or list or tuple", w_ob)
+ n = len(s)
+ if self.length >= 0 and n > self.length:
+ raise operationerrfmt(space.w_IndexError,
+ "initializer unicode string is too long for '%s'"
+ " (got %d characters)",
+ self.name, n)
+ unichardata = rffi.cast(rffi.CWCHARP, cdata)
+ for i in range(n):
+ unichardata[i] = s[i]
+ if n != self.length:
+ unichardata[n] = u'\x00'
+ else:
+ raise self._convert_error("list or tuple", w_ob)
+
class W_CTypePtrBase(W_CTypePtrOrArray):
# base class for both pointers and pointers-to-functions
@@ -125,7 +177,6 @@
return W_CTypePtrOrArray.unicode(self, cdataobj)
def newp(self, w_init):
- from pypy.module._cffi_backend import ctypeprim
space = self.space
ctitem = self.ctitem
datasize = ctitem.size
@@ -168,3 +219,47 @@
self.name)
p = rffi.ptradd(cdata, i * self.ctitem.size)
return cdataobj.W_CData(space, p, self)
+
+ def _prepare_pointer_call_argument(self, w_init):
+ space = self.space
+ if (space.isinstance_w(w_init, space.w_list) or
+ space.isinstance_w(w_init, space.w_tuple)):
+ length = space.int_w(space.len(w_init))
+ elif space.isinstance_w(w_init, space.w_basestring):
+ # from a string, we add the null terminator
+ length = space.int_w(space.len(w_init)) + 1
+ else:
+ return lltype.nullptr(rffi.CCHARP.TO)
+ if self.ctitem.size <= 0:
+ return lltype.nullptr(rffi.CCHARP.TO)
+ try:
+ datasize = ovfcheck(length * self.ctitem.size)
+ except OverflowError:
+ raise OperationError(space.w_OverflowError,
+ space.wrap("array size would overflow a ssize_t"))
+ result = lltype.malloc(rffi.CCHARP.TO, datasize,
+ flavor='raw', zero=True)
+ try:
+ self.convert_array_from_object(result, w_init)
+ except Exception:
+ lltype.free(result, flavor='raw')
+ raise
+ return result
+
+ def convert_argument_from_object(self, cdata, w_ob):
+ from pypy.module._cffi_backend.ctypefunc import set_mustfree_flag
+ space = self.space
+ ob = space.interpclass_w(w_ob)
+ if isinstance(ob, cdataobj.W_CData):
+ buffer = lltype.nullptr(rffi.CCHARP.TO)
+ else:
+ buffer = self._prepare_pointer_call_argument(w_ob)
+ #
+ if buffer:
+ rffi.cast(rffi.CCHARPP, cdata)[0] = buffer
+ set_mustfree_flag(cdata, True)
+ return True
+ else:
+ set_mustfree_flag(cdata, False)
+ self.convert_from_object(cdata, w_ob)
+ return False
More information about the pypy-commit
mailing list