www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Article: D Exceptions and C Callbacks

reply "Mike Parker" <aldacron gmail.com> writes:
Shows how I like to deal with throwing exceptions from C 
callbacks in D. Target audience is beginner-level. Uses GLFW to 
demonstrate.

http://www.gamedev.net/page/resources/_/technical/general-programming/d-exceptions-and-c-callbacks-r3323
Aug 06 2013
next sibling parent reply "QAston" <qaston gmail.com> writes:
On Tuesday, 6 August 2013 at 15:05:22 UTC, Mike Parker wrote:
 Shows how I like to deal with throwing exceptions from C 
 callbacks in D. Target audience is beginner-level. Uses GLFW to 
 demonstrate.

 http://www.gamedev.net/page/resources/_/technical/general-programming/d-exceptions-and-c-callbacks-r3323
Good article, thanks. There's one thing though. You say than relying on coder's discipline is error prone and I totally agree with that. But your sollution requires coder to remember to wrap those callbacks in try-catches. Maybe modifying glfwSetWindowCloseCallback and similar functions to only accept nothrow functions is a good idea?
Aug 06 2013
parent reply "Mike Parker" <aldacron gmail.com> writes:
On Tuesday, 6 August 2013 at 17:54:34 UTC, QAston wrote:

 There's one thing though. You say than relying on coder's 
 discipline is error prone and I totally agree with that. But 
 your sollution requires coder to remember to wrap those 
 callbacks in try-catches.
Programming always requires a certain amount of discipline. Remembering to release resources when they are no longer needed, properly handling errors, being aware of the constraints of a particular API call. It's all differing degrees. I don't think it's too much trouble to wrap D function calls in try...catch blocks inside a C callback. It's a one-off thing for each callback and something that will likely be on the programmer's mind when a decision is made to implement such a solution. Properly handling arrays in C is an ongoing, full-time thing where it's easy to overlook a mistake now and again. So Id on't really see it as a problem.
 Maybe modifying glfwSetWindowCloseCallback and similar 
 functions to only accept nothrow functions is a good idea?
I'm not sure what you mean. That's a C function, which means it doesn't have any concept of D's nothrow. And, actually, the callbacks should be declared as nothrow anyway. Like: extern( C ) nothrow void function( GLFWwindow* ) glfwWindowCloseCallback; Any exceptions thrown by functions called inside the callback must be handled, regardless, if you don't want to lose them.
Aug 06 2013
parent reply Johannes Pfau <nospam example.com> writes:
Am Wed, 07 Aug 2013 03:33:28 +0200
schrieb "Mike Parker" <aldacron gmail.com>:

 
 Maybe modifying glfwSetWindowCloseCallback and similar 
 functions to only accept nothrow functions is a good idea?
I'm not sure what you mean. That's a C function, which means it doesn't have any concept of D's nothrow. And, actually, the callbacks should be declared as nothrow anyway. Like:
He meant declaring glfwSetWindowCloseCallback like this: alias extern(C) nothrow void function() callback; extern(C) void glfwSetWindowCloseCallback(callback cb); http://dpaste.dzfl.pl/0f23146f There's no difference in the generated code, but this way the compiler will complain if you pass a non-nothrow function to glfwSetWindowCloseCallback.
Aug 07 2013
next sibling parent reply "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 7 August 2013 at 07:10:21 UTC, Johannes Pfau wrote:
 Am Wed, 07 Aug 2013 03:33:28 +0200
 schrieb "Mike Parker" <aldacron gmail.com>:

 
 Maybe modifying glfwSetWindowCloseCallback and similar 
 functions to only accept nothrow functions is a good idea?
I'm not sure what you mean. That's a C function, which means it doesn't have any concept of D's nothrow. And, actually, the callbacks should be declared as nothrow anyway. Like:
He meant declaring glfwSetWindowCloseCallback like this: alias extern(C) nothrow void function() callback; extern(C) void glfwSetWindowCloseCallback(callback cb); http://dpaste.dzfl.pl/0f23146f There's no difference in the generated code, but this way the compiler will complain if you pass a non-nothrow function to glfwSetWindowCloseCallback.
Yeah, I see. I misunderstood. I agree that the callbacks should be declared as nothrow. In Derelict, all the C function pointers are declared as such. Apparently, I overlooked adding it to the callbacks.
Aug 07 2013
parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Wed, 07 Aug 2013 12:08:44 +0200
schrieb "Mike Parker" <aldacron gmail.com>:

 On Wednesday, 7 August 2013 at 07:10:21 UTC, Johannes Pfau wrote:
 Am Wed, 07 Aug 2013 03:33:28 +0200
 schrieb "Mike Parker" <aldacron gmail.com>:

 
 Maybe modifying glfwSetWindowCloseCallback and similar 
 functions to only accept nothrow functions is a good idea?
I'm not sure what you mean. That's a C function, which means it doesn't have any concept of D's nothrow. And, actually, the callbacks should be declared as nothrow anyway. Like:
He meant declaring glfwSetWindowCloseCallback like this: alias extern(C) nothrow void function() callback; extern(C) void glfwSetWindowCloseCallback(callback cb); http://dpaste.dzfl.pl/0f23146f There's no difference in the generated code, but this way the compiler will complain if you pass a non-nothrow function to glfwSetWindowCloseCallback.
Yeah, I see. I misunderstood. I agree that the callbacks should be declared as nothrow. In Derelict, all the C function pointers are declared as such. Apparently, I overlooked adding it to the callbacks.
I recently proposed using nothrow in GtkD as well. This article was kind of a coincidence now. Yes, it is a real issue with binding to C code unfortunately. Especially on amd64 with GCC compiled stuff since it omits the stack frame that DMD requires to unwind the stack resulting in immediate crashes (druntime HLTs the execution) as soon as you throw an exception from a callback. -- Marco
Aug 08 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/8/2013 6:48 AM, Marco Leise wrote:
 I recently proposed using nothrow in GtkD as well. This
 article was kind of a coincidence now. Yes, it is a real issue
 with binding to C code unfortunately. Especially on amd64 with
 GCC compiled stuff since it omits the stack frame that DMD
 requires to unwind the stack resulting in immediate crashes
 (druntime HLTs the execution) as soon as you throw an
 exception from a callback.
I agree that C callbacks called from C code should be nothrow. At a minimum, the C code that calls the callback is not going to be expecting an exit via exception, and so may leave things in an indeterminate state.
Aug 08 2013
next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Thu, 08 Aug 2013 11:33:28 -0700
schrieb Walter Bright <newshound2 digitalmars.com>:

 On 8/8/2013 6:48 AM, Marco Leise wrote:
 I recently proposed using nothrow in GtkD as well. This
 article was kind of a coincidence now. Yes, it is a real issue
 with binding to C code unfortunately. Especially on amd64 with
 GCC compiled stuff since it omits the stack frame that DMD
 requires to unwind the stack resulting in immediate crashes
 (druntime HLTs the execution) as soon as you throw an
 exception from a callback.
I agree that C callbacks called from C code should be nothrow. At a minimum, the C code that calls the callback is not going to be expecting an exit via exception, and so may leave things in an indeterminate state.
Just for completeness: In a recent discussion on IRC I learned that vendor specific attributes exist for C compilers to mark functions as "ok to use with exceptions". -- Marco
Aug 08 2013
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 8/8/13, Walter Bright <newshound2 digitalmars.com> wrote:
 I agree that C callbacks called from C code should be nothrow.

 At a minimum, the C code that calls the callback is not going to be
 expecting an
 exit via exception, and so may leave things in an indeterminate state.
What about Error and Throwable? I think those shouldn't pass to the C code either. Unforunately 'nothrow' is a misnomer because it really means 'noexception', it allows both Error and Throwable to propagate from nothrow functions.
Aug 08 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/8/2013 2:27 PM, Andrej Mitrovic wrote:
 What about Error and Throwable? I think those shouldn't pass to the C
 code either. Unforunately 'nothrow' is a misnomer because it really
 means 'noexception', it allows both Error and Throwable to propagate
 from nothrow functions.
You're generally on your own with Error and Throwable going across foreign code.
Aug 10 2013
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 8/7/13, Johannes Pfau <nospam example.com> wrote:
 http://dpaste.dzfl.pl/0f23146f
 There's no difference in the generated code, but this way the compiler
 will complain if you pass a non-nothrow function to
 glfwSetWindowCloseCallback.
Although this only stops Exception types from propagating. Error and Throwable will still be allowed to be thrown. I would find it dangerous if a C library ends up swallowing a Throwable and continues execution like nothing happened.
Aug 07 2013
prev sibling parent reply "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
On Tuesday, 6 August 2013 at 15:05:22 UTC, Mike Parker wrote:
 Shows how I like to deal with throwing exceptions from C 
 callbacks in D. Target audience is beginner-level. Uses GLFW to 
 demonstrate.

 http://www.gamedev.net/page/resources/_/technical/general-programming/d-exceptions-and-c-callbacks-r3323
Nice article. A few minor corrections: - In your second code sample, the D translation of the C code, the line glfwSetWindowCloseCallback( &onWindowClose ); should read either glfwSetWindowCloseCallback( win, &onWindowClose ); or win.glfwSetWindowCloseCallback( &onWindowClose ); Maybe point out both are possible, but perhaps this is out of the scope of the article. - When explaining the difference between D Throwable, Exception, and Error, you write: The latter is analagous to Java's RuntimeException in that it is not intended to be caught. It should be thrown to indicate an unrecoverable error in the program. Java uses Error for unrecoverable errors too. RuntimeExceptions are recoverable and meant to be catched. It would be more accurate to say D lacks Java's checked exceptions, D exceptions are like Java's RuntimeExceptions, and D Errors are like Java Errors.
Aug 09 2013
parent "Mike Parker" <aldacron gmail.com> writes:
On Friday, 9 August 2013 at 14:08:48 UTC, Rene Zwanenburg wrote:

 - In your second code sample, the D translation of the C code, 
 the line
     glfwSetWindowCloseCallback( &onWindowClose );
   should read either
     glfwSetWindowCloseCallback( win, &onWindowClose );
   or
     win.glfwSetWindowCloseCallback( &onWindowClose );
Thanks! That was an oversight. I've corrected it.
 - When explaining the difference between D Throwable, 
 Exception, and Error, you write:
     The latter is analagous to Java's RuntimeException in that
     it is not intended to be caught. It should be thrown to
     indicate an unrecoverable error in the program.
   Java uses Error for unrecoverable errors too. 
 RuntimeExceptions are recoverable and meant to be catched. It 
 would be more accurate to say D lacks Java's checked 
 exceptions, D exceptions are like Java's RuntimeExceptions, and 
 D Errors are like Java Errors.
I just removed the reference to Java entirely. Thanks for pointing that out. I've had it in my head for years that RuntimeException was for unrecoverable errors.
Aug 09 2013