@@ -111,6 +111,16 @@ struct PythonAlreadySetInDestructor {
111111 py::str s;
112112};
113113
114+ struct CustomData {
115+ CustomData (const std::string &a) : a(a) {}
116+ std::string a;
117+ };
118+
119+ struct MyException7 {
120+ MyException7 (const CustomData &message) : message(message) {}
121+ CustomData message;
122+ };
123+
114124TEST_SUBMODULE (exceptions, m) {
115125 m.def (" throw_std_exception" ,
116126 []() { throw std::runtime_error (" This exception was intentionally thrown." ); });
@@ -385,4 +395,32 @@ TEST_SUBMODULE(exceptions, m) {
385395
386396 // m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
387397 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> storage;
409+ storage.call_once_and_store_result ([&]() {
410+ auto mod = py::module_::import (" custom_exceptions" );
411+ py::object obj = mod.attr (" PythonMyException7" );
412+ return obj;
413+ });
414+
415+ py::register_local_exception_translator ([](std::exception_ptr p) {
416+ try {
417+ if (p) {
418+ std::rethrow_exception (p);
419+ }
420+ } catch (const MyException7 &e) {
421+ auto obj = storage.get_stored ();
422+ py::object obj2 = obj (e.message );
423+ PyErr_SetObject (PyExc_Exception, obj2.ptr ());
424+ }
425+ });
388426}
0 commit comments