catch exceptions in method calls too
This commit is contained in:
1 parent
f14f0a8f20
commit
262c88f846
5 files changed
+56
-2
No files matched your search
+27
-1
@@ -13,6 +13,8 @@ from typehandlers import codesink
|
||||
import overloading
|
||||
import settings
|
||||
import utils
|
||||
from cppexception import CppException
|
||||
|
||||
|
||||
class CppMethod(ForwardWrapperBase):
|
||||
"""
|
||||
@@ -23,7 +25,7 @@ class CppMethod(ForwardWrapperBase):
|
||||
template_parameters=(), is_virtual=None, is_const=False,
|
||||
unblock_threads=None, is_pure_virtual=False,
|
||||
custom_template_method_name=None, visibility='public',
|
||||
custom_name=None, deprecated=False, docstring=None):
|
||||
custom_name=None, deprecated=False, docstring=None, throw=()):
|
||||
"""
|
||||
Create an object the generates code to wrap a C++ class method.
|
||||
|
||||
@@ -66,6 +68,9 @@ class CppMethod(ForwardWrapperBase):
|
||||
- False: Not deprecated
|
||||
- True: Deprecated
|
||||
- "message": Deprecated, and deprecation warning contains the given message
|
||||
|
||||
@param throw: list of C++ exceptions that the function may throw
|
||||
@type throw: list of L{CppException}
|
||||
"""
|
||||
self.stack_where_defined = traceback.extract_stack()
|
||||
|
||||
@@ -114,6 +119,10 @@ class CppMethod(ForwardWrapperBase):
|
||||
unblock_threads=unblock_threads)
|
||||
self.deprecated = deprecated
|
||||
|
||||
for t in throw:
|
||||
assert isinstance(t, CppException)
|
||||
self.throw = list(throw)
|
||||
|
||||
def set_helper_class(self, helper_class):
|
||||
"Set the C++ helper class, which is used for overriding virtual methods"
|
||||
self._helper_class = helper_class
|
||||
@@ -189,6 +198,12 @@ class CppMethod(ForwardWrapperBase):
|
||||
method = '%s::%s%s' % (class_.full_name, self.method_name, template_params)
|
||||
else:
|
||||
method = 'self->obj->%s%s' % (self.method_name, template_params)
|
||||
|
||||
|
||||
if self.throw:
|
||||
self.before_call.write_code('try\n{')
|
||||
self.before_call.indent()
|
||||
|
||||
if self.return_value.ctype == 'void':
|
||||
self.before_call.write_code(
|
||||
'%s(%s);' %
|
||||
@@ -203,6 +218,17 @@ class CppMethod(ForwardWrapperBase):
|
||||
'retval = %s(%s);' %
|
||||
(method, ", ".join(self.call_params)))
|
||||
|
||||
if self.throw:
|
||||
for exc in self.throw:
|
||||
self.before_call.unindent()
|
||||
self.before_call.write_code('} catch (%s const &exc) {' % exc.full_name)
|
||||
self.before_call.indent()
|
||||
self.before_call.write_cleanup()
|
||||
self.before_call.write_code('PyErr_SetNone((PyObject *) %s);\nreturn NULL;' % exc.pytypestruct)
|
||||
self.before_call.unindent()
|
||||
self.before_call.write_code('}')
|
||||
|
||||
|
||||
def _before_return_hook(self):
|
||||
"""hook that post-processes parameters and check for custodian=<n>
|
||||
CppClass parameters"""
|
||||
|
||||
+14
-1
@@ -434,7 +434,20 @@ namespace xpto
|
||||
}
|
||||
}
|
||||
|
||||
double my_inverse_func (double x) throw (DomainError)
|
||||
double
|
||||
my_inverse_func (double x) throw (DomainError)
|
||||
{
|
||||
if (x == 0)
|
||||
{
|
||||
DomainError ex;
|
||||
ex.message = "value must be != 0";
|
||||
throw ex;
|
||||
}
|
||||
return 1/x;
|
||||
}
|
||||
|
||||
double
|
||||
ClassThatThrows::my_inverse_method (double x) throw (DomainError)
|
||||
{
|
||||
if (x == 0)
|
||||
{
|
||||
|
||||
@@ -1046,6 +1046,11 @@ struct DomainError : public Error
|
||||
// returns 1/x, raises DomainError if x == 0
|
||||
double my_inverse_func (double x) throw (DomainError);
|
||||
|
||||
struct ClassThatThrows
|
||||
{
|
||||
// returns 1/x, raises DomainError if x == 0
|
||||
double my_inverse_method (double x) throw (DomainError);
|
||||
};
|
||||
|
||||
|
||||
#endif /* !FOO_H_ */
|
||||
@@ -500,6 +500,10 @@ int %s::custom_method_added_by_a_hook(int x)
|
||||
mod.add_function('my_inverse_func', 'double', [Parameter.new('double', 'x')],
|
||||
throw=[DomainError])
|
||||
|
||||
ClassThatThrows = mod.add_struct('ClassThatThrows')
|
||||
ClassThatThrows.add_method('my_inverse_method', 'double', [Parameter.new('double', 'x')],
|
||||
throw=[DomainError])
|
||||
|
||||
|
||||
#### --- error handler ---
|
||||
class MyErrorHandler(pybindgen.settings.ErrorHandler):
|
||||
|
||||
@@ -1166,5 +1166,11 @@ class TestFoo(unittest.TestCase):
|
||||
self.assertEqual(y, 0.5)
|
||||
self.assertRaises(foo.DomainError, foo.my_inverse_func, 0)
|
||||
|
||||
def test_method_exception(self):
|
||||
c = foo.ClassThatThrows()
|
||||
y = c.my_inverse_method(2)
|
||||
self.assertEqual(y, 0.5)
|
||||
self.assertRaises(foo.DomainError, c.my_inverse_method, 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user