[pypy-svn] pypy jitypes2: move the logic for how to unwrap ctypes values into _ffi compatible values from the Function class to the various _CData classes; this will probably make things easier to optimize later
antocuni
commits-noreply at bitbucket.org
Thu Jan 27 23:52:31 CET 2011
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r41412:8cf4b50263c8
Date: 2011-01-26 11:54 +0100
http://bitbucket.org/pypy/pypy/changeset/8cf4b50263c8/
Log: move the logic for how to unwrap ctypes values into _ffi compatible
values from the Function class to the various _CData classes; this
will probably make things easier to optimize later
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -206,6 +206,9 @@
def _get_buffer_value(self):
return self._buffer.buffer
+ def _to_ffi_param(self):
+ return self._get_buffer_value()
+
ARRAY_CACHE = {}
def create_array_type(base, length):
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -228,9 +228,7 @@
if argtypes is None:
argtypes = []
- args = self._convert_args(argtypes, args)
- argtypes = [type(arg) for arg in args]
- newargs = self._unwrap_args(argtypes, args)
+ newargs, argtypes = self._convert_args(argtypes, args)
funcptr = self._getfuncptr(argtypes, self._restype_, thisarg)
result = self._call_funcptr(funcptr, *newargs)
@@ -316,15 +314,19 @@
pass
raise
- @staticmethod
- def _conv_param(argtype, arg):
+ @classmethod
+ def _conv_param(cls, argtype, arg):
+ if isinstance(argtype, _CDataMeta):
+ #arg = argtype.from_param(arg)
+ arg = argtype.get_ffi_param(arg)
+ return arg, argtype
+
if argtype is not None:
arg = argtype.from_param(arg)
if hasattr(arg, '_as_parameter_'):
arg = arg._as_parameter_
if isinstance(arg, _CData):
- # The usual case when argtype is defined
- return arg
+ return arg._to_ffi_param(), type(arg)
#
# non-usual case: we do the import here to save a lot of code in the
# jit trace of the normal case
@@ -341,10 +343,11 @@
else:
raise TypeError("Don't know how to handle %s" % (arg,))
- return cobj
+ return cobj._to_ffi_param(), type(cobj)
def _convert_args(self, argtypes, args):
- wrapped_args = []
+ newargs = []
+ newargtypes = []
consumed = 0
for i, argtype in enumerate(argtypes):
@@ -365,7 +368,8 @@
import ctypes
val = argtype._type_()
wrapped = (val, ctypes.byref(val))
- wrapped_args.append(wrapped)
+ newargs.append(wrapped._to_ffi_param())
+ newargtypes.append(type(wrapped))
continue
elif idlflag == PARAMFLAG_FIN | PARAMFLAG_FLCID:
# Always taken from defaultvalue if given,
@@ -373,8 +377,9 @@
val = defaultvalue
if val is None:
val = 0
- wrapped = self._conv_param(argtype, val)
- wrapped_args.append(wrapped)
+ newarg, newargtype = self._conv_param(argtype, val)
+ newargs.append(newarg)
+ newargtypes.append(newargtype)
continue
else:
raise NotImplementedError(
@@ -388,45 +393,24 @@
raise TypeError("Not enough arguments")
try:
- wrapped = self._conv_param(argtype, arg)
+ newarg, newargtype = self._conv_param(argtype, arg)
except (UnicodeError, TypeError, ValueError), e:
raise ArgumentError(str(e))
- wrapped_args.append(wrapped)
+ newargs.append(newarg)
+ newargtypes.append(newargtype)
consumed += 1
- if len(wrapped_args) < len(args):
- extra = args[len(wrapped_args):]
- argtypes = list(argtypes)
+ if len(newargs) < len(args):
+ extra = args[len(newargs):]
for i, arg in enumerate(extra):
try:
- wrapped = self._conv_param(None, arg)
+ newarg, newargtype = self._conv_param(None, arg)
except (UnicodeError, TypeError, ValueError), e:
raise ArgumentError(str(e))
- wrapped_args.append(wrapped)
- return wrapped_args
+ newargs.append(newarg)
+ newargtypes.append(newargtype)
+ return newargs, newargtypes
-
- def _unwrap_args(self, argtypes, args):
- """
- Convert from ctypes high-level values to low-level values suitables to
- be passed to _ffi
- """
- assert len(argtypes) == len(args)
- newargs = []
- for argtype, arg in zip(argtypes, args):
- value = self._unwrap_single_arg(argtype, arg)
- newargs.append(value)
- return newargs
-
- def _unwrap_single_arg(self, argtype, arg):
- shape = argtype._ffiargshape
- if isinstance(shape, str) and shape in "POszZ": # pointer types
- value = arg._get_buffer_value()
- elif is_struct_shape(shape):
- value = arg._buffer
- else:
- value = arg.value
- return value
def _wrap_result(self, restype, result):
"""
@@ -557,9 +541,7 @@
assert self._argtypes_ is not None
argtypes = self._argtypes_
thisarg = None
- args = self._convert_args(argtypes, args)
- argtypes = [type(args[0])]
- newargs = self._unwrap_args(argtypes, args)
+ newargs, argtypes = self._convert_args(argtypes, args)
restype = self._restype_
funcptr = self._getfuncptr(argtypes, restype, thisarg)
result = self._call_funcptr(funcptr, *newargs)
@@ -572,13 +554,10 @@
"""
assert self._paramflags is None
try:
- wrapped_args = [self._conv_param(argtypes[0], args[0])]
+ wrapped_args = [self._conv_param(argtypes[0], args[0])[0]]
except (UnicodeError, TypeError, ValueError), e:
raise ArgumentError(str(e))
assert len(wrapped_args) == len(args)
- return wrapped_args
-
- def _unwrap_args(self, argtypes, args):
- return [self._unwrap_single_arg(argtypes[0], args[0])]
+ return wrapped_args, argtypes
return CFuncPtr_1
diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py
--- a/lib_pypy/_ctypes/primitive.py
+++ b/lib_pypy/_ctypes/primitive.py
@@ -247,7 +247,7 @@
else:
self._buffer[0] = 0 # VARIANT_FALSE
result.value = property(_getvalue, _setvalue)
-
+
return result
from_address = cdata_from_address
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -239,6 +239,9 @@
def _get_buffer_value(self):
return self._buffer.buffer
+ def _to_ffi_param(self):
+ return self._buffer
+
class StructureMeta(StructOrUnionMeta):
_is_union = False
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -47,6 +47,9 @@
else:
return self.from_param(as_parameter)
+ def get_ffi_param(self, value):
+ return self.from_param(value)._to_ffi_param()
+
def _CData_output(self, resbuffer, base=None, index=-1):
#assert isinstance(resbuffer, _rawffi.ArrayInstance)
"""Used when data exits ctypes and goes into user code.
@@ -120,6 +123,12 @@
def _get_buffer_value(self):
return self._buffer[0]
+ def _to_ffi_param(self):
+ if self.__class__._is_pointer_like():
+ return self._get_buffer_value()
+ else:
+ return self.value
+
def __buffer__(self):
return buffer(self._buffer)
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py b/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
@@ -12,8 +12,8 @@
from _ctypes.function import CFuncPtr
def guess(value):
- cobj = CFuncPtr._conv_param(None, value)
- return type(cobj)
+ cobj, ctype = CFuncPtr._conv_param(None, value)
+ return ctype
assert guess(13) == c_int
assert guess(0) == c_int
More information about the Pypy-commit
mailing list