digitalmars.D - Catching C++ Exceptions in D
- Walter Bright (21/21) Jan 05 2016 We have a design now, driven by:
- Daniel N (3/4) Jan 05 2016 Sounds good(assuming one gets a compilation error when this rule
- Jakob Ovrum (27/50) Jan 05 2016 Because C++-throw copies the exception and thus slices base class
- Walter Bright (2/8) Jan 05 2016 It's just a limitation for now in order to get things moving.
- Jacob Carlborg (4/5) Jan 05 2016 What happens if one just calls "__cxa_throw"?
- Walter Bright (2/5) Jan 05 2016 I don't know.
- Jakob Ovrum (3/13) Jan 05 2016 Of course, C++ doesn't have immutable, so this isn't really an
- Elie Morisse (3/8) Jan 05 2016 why not distinguish C++ exceptions from D ones in the personality
- Walter Bright (2/3) Jan 05 2016 How?
- Jacob Carlborg (6/7) Jan 05 2016 There's something called "__cxa_current_exception_type" [1], can that be...
- Walter Bright (2/6) Jan 05 2016 That only works with C++ types, not D types.
- Elie Morisse (16/20) Jan 05 2016 Are you aware of
- Walter Bright (7/14) Jan 05 2016 No, thanks for pointing it out. Your solution is clever. I'll have to th...
- Jacob Carlborg (5/6) Jan 05 2016 Seems to be easy with "__cxa_rethrow", takes no arguments and doesn't
- Jakob Ovrum (4/6) Jan 05 2016 Does this work with rethrow? What if a D exception is thrown from
- Jakob Ovrum (3/10) Jan 05 2016 To clarify, I mean a catch block in D code that catches as C++
- Walter Bright (3/8) Jan 05 2016 My understanding is that rethrow invokes the copy constructor, so the or...
- Andrei Alexandrescu (18/30) Jan 06 2016 To clarify what C++ does, consider:
We have a design now, driven by: 1. compatibility with best practice exceptions in C++ (i.e. never catch by value, etc.) 2. minimizing implementation difficulty 3. fitting in with D semantics 4. pushing as much as we can into the C++ compiler ---------------------------------------------------------- C++ exceptions cannot be thrown from D. If you must throw a C++ exception, write and call a C++ function to do it. C++ rethrows as well need to be done by calling a C++ function to do it. D code can only catch C++ exceptions declared as: extern (C++) class Identifier { ... } Best practice in C++ is catching by const&, and D's classes fit right in with that. At the exit of a catch clause, the destructor on the caught C++ exception will be run, as would be expected by C++ programmers. Because of running the destructors, C++ exceptions cannot be caught in safe code. Function bodies cannot mix catching C++ and D exceptions. (The reason is C++ catch types need to be distinguished from D catch types, and the most straightforward method to deal with that is have a different 'personality' function for functions that catch C++ exceptions.) However, nested functions can catch different ones than their enclosing function.
Jan 05 2016
On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:Function bodies cannot mix catching C++ and D exceptions.Sounds good(assuming one gets a compilation error when this rule is broken).
Jan 05 2016
On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:We have a design now, driven by: 1. compatibility with best practice exceptions in C++ (i.e. never catch by value, etc.) 2. minimizing implementation difficulty 3. fitting in with D semantics 4. pushing as much as we can into the C++ compiler ---------------------------------------------------------- C++ exceptions cannot be thrown from D. If you must throw a C++ exception, write and call a C++ function to do it.Because C++-throw copies the exception and thus slices base class references, this is actually quite inconvenient. There's no One Helper Function that can handle a whole swath of cases. Just wanted to mention it, not saying this should be an important or priority feature, it's just an inconvenience after all.D code can only catch C++ exceptions declared as: extern (C++) class Identifier { ... } Best practice in C++ is catching by const&, and D's classes fit right in with that.Well, except for the const part. D exceptions are completely broken when it comes to const and immutable. It seems to have been overlooked during the transition to D2.At the exit of a catch clause, the destructor on the caught C++ exception will be run, as would be expected by C++ programmers. Because of running the destructors, C++ exceptions cannot be caught in safe code.Nice.Function bodies cannot mix catching C++ and D exceptions. (The reason is C++ catch types need to be distinguished from D catch types, and the most straightforward method to deal with that is have a different 'personality' function for functions that catch C++ exceptions.) However, nested functions can catch different ones than their enclosing function.Nice. Thanks for doing this. I'm excited about C++ interop. There was a project called OpenMorrowind which dropped D1+C++ in favour of just C++ because the C interface was too tedious. I bet if they had what we have now they wouldn't have done that (assuming we fix the mangling bugs for C++ function templates and then provide stdc++ bindings). Switching to DWARF has another benefit - it allows throwing D exceptions past C stack frames. Some people seem to think this is always wrong, but some C libraries are designed to support throwing or long jumping from certain callbacks, including libev and liblua. This tremendously helps the usability of D wrappers around such libraries. Currently I work around it by providing custom-compiled binaries of the C libraries with intact stack frames. This is also cause to be sad about our DWARF support being limited to Linux64. Anyway, thanks!
Jan 05 2016
On 1/5/2016 10:22 AM, Jakob Ovrum wrote:It's just a limitation for now in order to get things moving.C++ exceptions cannot be thrown from D. If you must throw a C++ exception, write and call a C++ function to do it.Because C++-throw copies the exception and thus slices base class references, this is actually quite inconvenient. There's no One Helper Function that can handle a whole swath of cases. Just wanted to mention it, not saying this should be an important or priority feature, it's just an inconvenience after all.
Jan 05 2016
On 2016-01-05 19:49, Walter Bright wrote:It's just a limitation for now in order to get things moving.What happens if one just calls "__cxa_throw"? -- /Jacob Carlborg
Jan 05 2016
On 1/5/2016 1:19 PM, Jacob Carlborg wrote:On 2016-01-05 19:49, Walter Bright wrote:I don't know.It's just a limitation for now in order to get things moving.What happens if one just calls "__cxa_throw"?
Jan 05 2016
On Tuesday, 5 January 2016 at 18:22:56 UTC, Jakob Ovrum wrote:On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:Of course, C++ doesn't have immutable, so this isn't really an issue in practice for C++ exceptions.D code can only catch C++ exceptions declared as: extern (C++) class Identifier { ... } Best practice in C++ is catching by const&, and D's classes fit right in with that.Well, except for the const part. D exceptions are completely broken when it comes to const and immutable. It seems to have been overlooked during the transition to D2.
Jan 05 2016
On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:Function bodies cannot mix catching C++ and D exceptions. (The reason is C++ catch types need to be distinguished from D catch types, and the most straightforward method to deal with that is have a different 'personality' function for functions that catch C++ exceptions.)why not distinguish C++ exceptions from D ones in the personality routine?
Jan 05 2016
On 1/5/2016 10:51 AM, Elie Morisse wrote:why not distinguish C++ exceptions from D ones in the personality routine?How?
Jan 05 2016
On 2016-01-05 21:07, Walter Bright wrote:How?There's something called "__cxa_current_exception_type" [1], can that be of use? [1] http://libcxxabi.llvm.org/spec.html -- /Jacob Carlborg
Jan 05 2016
On 1/5/2016 1:22 PM, Jacob Carlborg wrote:On 2016-01-05 21:07, Walter Bright wrote:That only works with C++ types, not D types.How?There's something called "__cxa_current_exception_type" [1], can that be of use? [1] http://libcxxabi.llvm.org/spec.html
Jan 05 2016
On Tuesday, 5 January 2016 at 20:07:11 UTC, Walter Bright wrote:On 1/5/2016 10:51 AM, Elie Morisse wrote:Are you aware of https://syniurgeblog.wordpress.com/2015/11/20/calypso-catching-cpp-exceptions-in-d/? For DMD if the personality functions sees the C++ exception class (3rd arg passed to the personality func) would it be hard to make it look for C++ catch clauses? With Calypso those catch clauses are std::type_info pointers wrapped inside a D class so that cast() is used to differentiate D catch clauses from C++ ones in the action table, and the personality function match those std::type_info against the one from the C++ exception header by calling the virtual function type_info::__do_catch(type_info*). A single personality routine handles both D and C++ exceptions, and I don't think having a different one for C++ exceptions would make things much easier. The tricky part for DMD is probably the std::type_info generation.why not distinguish C++ exceptions from D ones in the personality routine?How?
Jan 05 2016
On 1/5/2016 2:58 PM, Elie Morisse wrote:On Tuesday, 5 January 2016 at 20:07:11 UTC, Walter Bright wrote:No, thanks for pointing it out. Your solution is clever. I'll have to think about which method is better. Also, catch (C++)(ref exception e) the (C++) seems redundant. The compiler can look at the type of e, and determine if it is C++ or not.On 1/5/2016 10:51 AM, Elie Morisse wrote:Are you aware of https://syniurgeblog.wordpress.com/2015/11/20/calypso-catching-cpp-exceptions-in-d/?why not distinguish C++ exceptions from D ones in the personality routine?How?
Jan 05 2016
On 2016-01-05 18:23, Walter Bright wrote:C++ rethrows as well need to be done by calling a C++ function to do it.Seems to be easy with "__cxa_rethrow", takes no arguments and doesn't return anything. -- /Jacob Carlborg
Jan 05 2016
On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:At the exit of a catch clause, the destructor on the caught C++ exception will be run, as would be expected by C++ programmers.Does this work with rethrow? What if a D exception is thrown from a C++ catch block - will the C++ exception still be destroyed properly?
Jan 05 2016
On Tuesday, 5 January 2016 at 21:30:21 UTC, Jakob Ovrum wrote:On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:To clarify, I mean a catch block in D code that catches as C++ exception.At the exit of a catch clause, the destructor on the caught C++ exception will be run, as would be expected by C++ programmers.Does this work with rethrow? What if a D exception is thrown from a C++ catch block - will the C++ exception still be destroyed properly?
Jan 05 2016
On 1/5/2016 1:30 PM, Jakob Ovrum wrote:On Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:My understanding is that rethrow invokes the copy constructor, so the original can still be destroyed.At the exit of a catch clause, the destructor on the caught C++ exception will be run, as would be expected by C++ programmers.Does this work with rethrow? What if a D exception is thrown from a C++ catch block - will the C++ exception still be destroyed properly?
Jan 05 2016
On 01/05/2016 06:56 PM, Walter Bright wrote:On 1/5/2016 1:30 PM, Jakob Ovrum wrote:To clarify what C++ does, consider: try { ... } catch (std::exception& e) { throw e; } This throws a copy of e and is almost always not the desired/expected behavior because the original dynamic type of e (which may be a class derived from std::exception) is lost. Now consider: try { ... } catch (std::exception& e) { throw; } In this case no copy is created. The same exact dynamic object continues to be thrown up the chain. AndreiOn Tuesday, 5 January 2016 at 17:23:38 UTC, Walter Bright wrote:My understanding is that rethrow invokes the copy constructor, so the original can still be destroyed.At the exit of a catch clause, the destructor on the caught C++ exception will be run, as would be expected by C++ programmers.Does this work with rethrow? What if a D exception is thrown from a C++ catch block - will the C++ exception still be destroyed properly?
Jan 06 2016