blob: 41d51d84f4fb6eec28e8e418bfef4123f511286d [file] [log] [blame]
Pim Schellart5a7d17f2016-06-17 17:35:59 -04001/*
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -04002 example/example-custom-exceptions.cpp -- exception translation
Pim Schellart5a7d17f2016-06-17 17:35:59 -04003
4 Copyright (c) 2016 Pim Schellart <P.Schellart@princeton.edu>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#include "example.h"
11
12// A type that should be raised as an exeption in Python
13class MyException : public std::exception {
14public:
15 explicit MyException(const char * m) : message{m} {}
16 virtual const char * what() const noexcept override {return message.c_str();}
17private:
18 std::string message = "";
19};
20
21// A type that should be translated to a standard Python exception
22class MyException2 : public std::exception {
23public:
24 explicit MyException2(const char * m) : message{m} {}
25 virtual const char * what() const noexcept override {return message.c_str();}
26private:
27 std::string message = "";
28};
29
30// A type that is not derived from std::exception (and is thus unknown)
31class MyException3 {
32public:
33 explicit MyException3(const char * m) : message{m} {}
34 virtual const char * what() const noexcept {return message.c_str();}
35private:
36 std::string message = "";
37};
38
39// A type that should be translated to MyException
40// and delegated to its exception translator
41class MyException4 : public std::exception {
42public:
43 explicit MyException4(const char * m) : message{m} {}
44 virtual const char * what() const noexcept override {return message.c_str();}
45private:
46 std::string message = "";
47};
48
49void throws1() {
50 throw MyException("this error should go to a custom type");
51}
52
53void throws2() {
54 throw MyException2("this error should go to a standard Python exception");
55}
56
57void throws3() {
58 throw MyException3("this error cannot be translated");
59}
60
61void throws4() {
62 throw MyException4("this error is rethrown");
63}
64
65void throws_logic_error() {
66 throw std::logic_error("this error should fall through to the standard handler");
67}
68
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040069void init_ex_custom_exceptions(py::module &m) {
Pim Schellart5a7d17f2016-06-17 17:35:59 -040070 // make a new custom exception and use it as a translation target
71 static py::exception<MyException> ex(m, "MyException");
72 py::register_exception_translator([](std::exception_ptr p) {
73 try {
74 if (p) std::rethrow_exception(p);
75 } catch (const MyException &e) {
76 PyErr_SetString(ex.ptr(), e.what());
77 }
78 });
79
80 // register new translator for MyException2
81 // no need to store anything here because this type will
82 // never by visible from Python
83 py::register_exception_translator([](std::exception_ptr p) {
84 try {
85 if (p) std::rethrow_exception(p);
86 } catch (const MyException2 &e) {
87 PyErr_SetString(PyExc_RuntimeError, e.what());
88 }
89 });
90
91 // register new translator for MyException4
92 // which will catch it and delegate to the previously registered
93 // translator for MyException by throwing a new exception
94 py::register_exception_translator([](std::exception_ptr p) {
95 try {
96 if (p) std::rethrow_exception(p);
97 } catch (const MyException4 &e) {
98 throw MyException(e.what());
99 }
100 });
101
102 m.def("throws1", &throws1);
103 m.def("throws2", &throws2);
104 m.def("throws3", &throws3);
105 m.def("throws4", &throws4);
106 m.def("throws_logic_error", &throws_logic_error);
107}
108