Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r45442:fef0408e477f Date: 2011-07-10 00:04 +0200 http://bitbucket.org/pypy/pypy/changeset/fef0408e477f/
Log: merge heads 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 @@ -48,7 +48,8 @@ return self.from_param(as_parameter) def get_ffi_param(self, value): - return self.from_param(value)._to_ffi_param() + cdata = self.from_param(value) + return cdata, cdata._to_ffi_param() def get_ffi_argtype(self): if self._ffiargtype: 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,12 +328,14 @@ "native COM method call without 'this' parameter" ) thisarg = cast(args[0], POINTER(POINTER(c_void_p))) - newargs, argtypes, outargs = self._convert_args(argtypes, args[1:], kwargs) + keepalives, newargs, argtypes, outargs = self._convert_args(argtypes, + args[1:], kwargs) newargs.insert(0, args[0].value) argtypes.insert(0, c_void_p) else: thisarg = None - newargs, argtypes, outargs = self._convert_args(argtypes, args, kwargs) + keepalives, newargs, argtypes, outargs = self._convert_args(argtypes, + args, kwargs) funcptr = self._getfuncptr(argtypes, self._restype_, thisarg) result = self._call_funcptr(funcptr, *newargs) @@ -437,16 +439,15 @@ @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 + cobj, ffiparam = argtype.get_ffi_param(arg) + return cobj, ffiparam, argtype if argtype is not None: arg = argtype.from_param(arg) if hasattr(arg, '_as_parameter_'): arg = arg._as_parameter_ if isinstance(arg, _CData): - return arg._to_ffi_param(), type(arg) + return arg, 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 @@ -463,11 +464,12 @@ else: raise TypeError("Don't know how to handle %s" % (arg,)) - return cobj._to_ffi_param(), type(cobj) + return cobj, cobj._to_ffi_param(), type(cobj) def _convert_args(self, argtypes, args, kwargs, marker=object()): newargs = [] outargs = [] + keepalives = [] newargtypes = [] total = len(args) paramflags = self._paramflags @@ -495,7 +497,8 @@ val = defval if val is marker: val = 0 - newarg, newargtype = self._conv_param(argtype, val) + keepalive, newarg, newargtype = self._conv_param(argtype, val) + keepalives.append(keepalive) newargs.append(newarg) newargtypes.append(newargtype) elif flag in (0, PARAMFLAG_FIN): @@ -511,28 +514,32 @@ raise TypeError("required argument '%s' missing" % name) else: raise TypeError("not enough arguments") - newarg, newargtype = self._conv_param(argtype, 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) - newarg, newargtype = self._conv_param(argtype, 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) + keepalives.append(keepalive) newargs.append(newarg) newargtypes.append(newargtype) else: raise ValueError("paramflag %d not yet implemented" % flag) else: try: - newarg, newargtype = self._conv_param(argtype, args[i]) + keepalive, newarg, newargtype = self._conv_param(argtype, args[i]) except (UnicodeError, TypeError, ValueError), e: raise ArgumentError(str(e)) + keepalives.append(keepalive) newargs.append(newarg) newargtypes.append(newargtype) inargs_idx += 1 @@ -541,12 +548,13 @@ extra = args[len(newargs):] for i, arg in enumerate(extra): try: - newarg, newargtype = self._conv_param(None, arg) + keepalive, newarg, newargtype = self._conv_param(None, arg) except (UnicodeError, TypeError, ValueError), e: raise ArgumentError(str(e)) + keepalives.append(keepalive) newargs.append(newarg) newargtypes.append(newargtype) - return newargs, newargtypes, outargs + return keepalives, newargs, newargtypes, outargs def _wrap_result(self, restype, result): 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 @@ -411,6 +411,23 @@ result = f("abcd", ord("b")) assert result == "bcd" + def test_keepalive_buffers(self, monkeypatch): + import gc + f = dll.my_strchr + f.argtypes = [c_char_p] + f.restype = c_char_p + # + orig__call_funcptr = f._call_funcptr + def _call_funcptr(funcptr, *newargs): + gc.collect() + gc.collect() + gc.collect() + return orig__call_funcptr(funcptr, *newargs) + monkeypatch.setattr(f, '_call_funcptr', _call_funcptr) + # + result = f("abcd", ord("b")) + assert result == "bcd" + def test_caching_bug_1(self): # the same test as test_call_some_args, with two extra lines # in the middle that trigger caching in f._ptr, which then 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,7 +12,7 @@ from _ctypes.function import CFuncPtr def guess(value): - cobj, ctype = CFuncPtr._conv_param(None, value) + _, cobj, ctype = CFuncPtr._conv_param(None, value) return ctype ## cobj = CFuncPtr._conv_param(None, value) ## return type(cobj) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit