@@ -111,6 +111,16 @@ struct PythonAlreadySetInDestructor {
111111 py::str s;
112112};
113113
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+
114124TEST_SUBMODULE (exceptions, m) {
115125 m.def (" throw_std_exception" ,
116126 []() { throw std::runtime_error (" This exception was intentionally thrown." ); });
@@ -385,4 +395,33 @@ 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>
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+ });
388427}
0 commit comments