Author: Armin Rigo <[email protected]>
Branch:
Changeset: r68400:160192d5cbdc
Date: 2013-12-08 10:46 +0100
http://bitbucket.org/pypy/pypy/changeset/160192d5cbdc/
Log: Fix for issue1655.
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
@@ -328,21 +328,23 @@
raise ValueError(
"native COM method call without 'this' parameter"
)
- thisarg = cast(args[0], POINTER(POINTER(c_void_p)))
- keepalives, newargs, argtypes, outargs =
self._convert_args(argtypes,
-
args[1:], kwargs)
- newargs.insert(0, args[0].value)
+ thisvalue = args.pop(0)
+ thisarg = cast(thisvalue, POINTER(POINTER(c_void_p)))
+ keepalives, newargs, argtypes, outargs, errcheckargs = (
+ self._convert_args(argtypes, args, kwargs))
+ args.insert(0, thisvalue)
+ newargs.insert(0, thisvalue.value)
argtypes.insert(0, c_void_p)
else:
thisarg = None
- keepalives, newargs, argtypes, outargs =
self._convert_args(argtypes,
- args,
kwargs)
+ keepalives, newargs, argtypes, outargs, errcheckargs = (
+ self._convert_args(argtypes, args, kwargs))
funcptr = self._getfuncptr(argtypes, self._restype_, thisarg)
result = self._call_funcptr(funcptr, *newargs)
- result = self._do_errcheck(result, args)
+ result, forced = self._do_errcheck(result, errcheckargs)
- if not outargs:
+ if not outargs or forced:
return result
from ctypes import c_void_p
@@ -384,15 +386,15 @@
def _do_errcheck(self, result, args):
# The 'errcheck' protocol
if self._errcheck_:
- v = self._errcheck_(result, self, args)
+ v = self._errcheck_(result, self, tuple(args))
# If the errcheck funtion failed, let it throw
# If the errcheck function returned newargs unchanged,
# continue normal processing.
# If the errcheck function returned something else,
# use that as result.
if v is not args:
- return v
- return result
+ return v, True
+ return result, False
def _getfuncptr_fromaddress(self, argtypes, restype):
address = self._get_address()
@@ -495,16 +497,16 @@
newargtypes = []
total = len(args)
paramflags = self._paramflags
- inargs_idx = 0
if not paramflags and total < len(argtypes):
raise TypeError("not enough arguments")
- for i, argtype in enumerate(argtypes):
- flag = 0
- name = None
- defval = marker
- if paramflags:
+ if paramflags:
+ errcheckargs = []
+ inargs_idx = 0
+ for i, argtype in enumerate(argtypes):
+ flag = 0
+ defval = marker
paramflag = paramflags[i]
paramlen = len(paramflag)
name = None
@@ -519,6 +521,7 @@
val = defval
if val is marker:
val = 0
+ errcheckargs.append(val)
keepalive, newarg, newargtype = self._conv_param(argtype,
val)
keepalives.append(keepalive)
newargs.append(newarg)
@@ -536,27 +539,31 @@
raise TypeError("required argument '%s' missing" %
name)
else:
raise TypeError("not enough arguments")
+ errcheckargs.append(val)
keepalive, newarg, newargtype = self._conv_param(argtype,
val)
keepalives.append(keepalive)
newargs.append(newarg)
newargtypes.append(newargtype)
elif flag == PARAMFLAG_FOUT:
if defval is not marker:
- outargs.append(defval)
+ val = defval
keepalive, newarg, newargtype =
self._conv_param(argtype, defval)
else:
import ctypes
val = argtype._type_()
- outargs.append(val)
keepalive = None
newarg = ctypes.byref(val)
newargtype = type(newarg)
+ errcheckargs.append(val)
+ outargs.append(val)
keepalives.append(keepalive)
newargs.append(newarg)
newargtypes.append(newargtype)
else:
raise ValueError("paramflag %d not yet implemented" % flag)
- else:
+ else:
+ errcheckargs = args
+ for i, argtype in enumerate(argtypes):
try:
keepalive, newarg, newargtype = self._conv_param(argtype,
args[i])
except (UnicodeError, TypeError, ValueError), e:
@@ -564,7 +571,6 @@
keepalives.append(keepalive)
newargs.append(newarg)
newargtypes.append(newargtype)
- inargs_idx += 1
if len(newargs) < len(args):
extra = args[len(newargs):]
@@ -576,7 +582,7 @@
keepalives.append(keepalive)
newargs.append(newarg)
newargtypes.append(newargtype)
- return keepalives, newargs, newargtypes, outargs
+ return keepalives, newargs, newargtypes, outargs, errcheckargs
@staticmethod
def _is_primitive(argtype):
@@ -699,7 +705,7 @@
funcptr = self._getfuncptr(argtypes, restype, thisarg)
try:
result = self._call_funcptr(funcptr, *args)
- result = self._do_errcheck(result, args)
+ result, _ = self._do_errcheck(result, args)
except (TypeError, ArgumentError, UnicodeDecodeError):
assert self._slowpath_allowed
return CFuncPtr.__call__(self, *args)
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
b/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
--- a/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
+++ b/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
@@ -567,3 +567,13 @@
errno = result + 1;
return result;
}
+
+EXPORT(int *) test_issue1655(char const *tag, int *len)
+{
+ static int data[] = { -1, -2, -3, -4 };
+ *len = -42;
+ if (strcmp(tag, "testing!") != 0)
+ return NULL;
+ *len = sizeof(data) / sizeof(data[0]);
+ return data;
+}
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
@@ -559,3 +559,25 @@
assert (res, n) == (42, 43)
set_errno(0)
assert get_errno() == 0
+
+ def test_issue1655(self):
+ def ret_list_p(icount):
+ def sz_array_p(obj, func, args):
+ assert ('.LP_c_int object' in repr(obj) or
+ '.LP_c_long object' in repr(obj))
+ assert repr(args) in ("('testing!', c_int(4))",
+ "('testing!', c_long(4))")
+ assert args[icount].value == 4
+ return [ obj[i] for i in range(args[icount].value) ]
+ return sz_array_p
+
+ get_data_prototype = CFUNCTYPE(POINTER(c_int),
+ c_char_p, POINTER(c_int))
+ get_data_paramflag = ((1,), (2,))
+ get_data_signature = ('test_issue1655', dll)
+
+ get_data = get_data_prototype( get_data_signature, get_data_paramflag )
+ assert get_data('testing!') == 4
+
+ get_data.errcheck = ret_list_p(1)
+ assert get_data('testing!') == [-1, -2, -3, -4]
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit