@@ -111,6 +111,16 @@ struct PythonAlreadySetInDestructor {
111
111
py::str s;
112
112
};
113
113
114
+ struct CustomData {
115
+ explicit CustomData (const std::string &a) : a(a) {}
116
+ std::string a;
117
+ };
118
+
119
+ struct MyException7 {
120
+ explicit MyException7 (const CustomData &message) : message(message) {}
121
+ CustomData message;
122
+ };
123
+
114
124
TEST_SUBMODULE (exceptions, m) {
115
125
m.def (" throw_std_exception" ,
116
126
[]() { throw std::runtime_error (" This exception was intentionally thrown." ); });
@@ -385,4 +395,33 @@ TEST_SUBMODULE(exceptions, m) {
385
395
386
396
// m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
387
397
m.def (" return_exception_void" , []() { return py::exception <void >(); });
398
+
399
+ m.def (" throws7" , []() {
400
+ auto data = CustomData (" abc" );
401
+ throw MyException7 (data);
402
+ });
403
+
404
+ py::class_<CustomData>(m, " CustomData" , py::module_local ())
405
+ .def (py::init<const std::string &>())
406
+ .def_readwrite (" a" , &CustomData::a);
407
+
408
+ PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object>
409
+ PythonMyException7_storage;
410
+ PythonMyException7_storage.call_once_and_store_result ([&]() {
411
+ auto mod = py::module_::import (" custom_exceptions" );
412
+ py::object obj = mod.attr (" PythonMyException7" );
413
+ return obj;
414
+ });
415
+
416
+ py::register_local_exception_translator ([](std::exception_ptr p) {
417
+ try {
418
+ if (p) {
419
+ std::rethrow_exception (p);
420
+ }
421
+ } catch (const MyException7 &e) {
422
+ auto exc_type = PythonMyException7_storage.get_stored ();
423
+ py::object exc_inst = exc_type (e.message );
424
+ PyErr_SetObject (PyExc_Exception, exc_inst.ptr ());
425
+ }
426
+ });
388
427
}
0 commit comments