Author: Armin Rigo <[email protected]>
Branch: hpy
Changeset: r98117:1b05295469eb
Date: 2019-11-18 18:38 +0100
http://bitbucket.org/pypy/pypy/changeset/1b05295469eb/
Log: (antocuni, arigo)
Allow llhelper functions to propagate exceptions from RPython to
RPython via C. This already works after translation, but we need to
convince ll2ctypes.
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py
b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -869,6 +869,9 @@
llinterp = LLInterpreter.current_interpreter
llinterp._store_exception(lle)
return 0
+ return ctypes_return_value(llres)
+
+ def ctypes_return_value(llres):
assert lltype.typeOf(llres) == T.TO.RESULT
if T.TO.RESULT is lltype.Void:
return None
@@ -891,7 +894,12 @@
# import pdb; pdb.post_mortem(sys.exc_traceback)
global _callback_exc_info
_callback_exc_info = sys.exc_info()
- raise
+ if hasattr(getattr(container, '_callable', None),
+ '_llhelper_can_raise_'):
+ llres = T.TO.RESULT._defl()
+ return ctypes_return_value(llres)
+ else:
+ raise
if isinstance(T.TO.RESULT, lltype.Ptr):
TMod = lltype.Ptr(lltype.FuncType(T.TO.ARGS,
@@ -974,7 +982,7 @@
return llobj
-def ctypes2lltype(T, cobj):
+def ctypes2lltype(T, cobj, force_real_ctypes_function=False):
"""Convert the ctypes object 'cobj' to its lltype equivalent.
'T' is the expected lltype type.
"""
@@ -1045,7 +1053,7 @@
# or goes out of scope, then we crash. CTypes is fun.
# It works if we cast it now to an int and back.
cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value)
- if cobjkey in _int2obj:
+ if cobjkey in _int2obj and not force_real_ctypes_function:
container = _int2obj[cobjkey]
else:
name = getattr(cobj, '__name__', '?')
diff --git a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
@@ -1,4 +1,4 @@
-import py
+import py, pytest
import sys, struct
import ctypes
from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
@@ -480,6 +480,28 @@
assert res == 42
assert not ALLOCATED # detects memory leaks in the test
+ def test_funcptr_can_raise(self, monkeypatch):
+ class FooError(Exception):
+ pass
+ def dummy(n):
+ raise FooError(n + 2)
+ dummy._llhelper_can_raise_ = True
+
+ FUNCTYPE = lltype.FuncType([lltype.Signed], lltype.Signed)
+ cdummy = lltype2ctypes(llhelper(lltype.Ptr(FUNCTYPE), dummy))
+ # here we pretend there is C in the middle
+ lldummy = ctypes2lltype(lltype.Ptr(FUNCTYPE), cdummy,
+ force_real_ctypes_function=True)
+ seen = []
+ def custom_except_hook(*args):
+ seen.append(args)
+ monkeypatch.setattr(sys, 'excepthook', custom_except_hook)
+ with pytest.raises(FooError) as exc:
+ lldummy(41)
+ assert exc.value.args == (41 + 2,)
+ assert not seen
+ assert not ALLOCATED # detects memory leaks in the test
+
def test_funcptr2(self):
FUNCTYPE = lltype.FuncType([rffi.CCHARP], rffi.LONG)
cstrlen = standard_c_lib.strlen
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit