nothrow function callbacks in extern(C) code - solution

Walter Bright via Digitalmars-d digitalmars-d at puremagic.com
Thu Jun 19 12:59:00 PDT 2014


With nothrow and @nogc annotations, we've been motivated to add these 
annotations to C system API functions, because obviously such functions aren't 
going to throw D exceptions or call the D garbage collector.

But this exposed a problem - functions like C's qsort() take a pointer to a 
callback function. The callback function, being supplied by the D programmer, 
may throw and may call the garbage collector. By requiring the callback function 
to be also nothrow @nogc, this is an unreasonable requirement besides breaking 
most existing D code that uses qsort().

This problem applies as well to the Windows APIs and the Posix APIs with callbacks.

The solution is to use overloading so that if your callback is nothrow, it will 
call the nothrow version of qsort, if it is throwable, it calls the throwable 
version of qsort.

Never mind that those two versions of qsort are actually the same function (!), 
even though D's type system regards them as different. Although this looks like 
an usafe hack, it actually is quite safe, presuming that the rest of the qsort 
code itself does not throw. This technique relies on the fact that extern(C) 
functions do not get their types mangled into the names.

Some example code:

   extern (C)         { alias int function() fp_t; }
   extern (C) nothrow { alias int function() fpnothrow_t; }

   extern (C)         int foo(int a, fp_t fp);
   extern (C) nothrow int foo(int a, fpnothrow_t fp);

   extern (C)         int bar();
   extern (C) nothrow int barnothrow();

   void test() {
     foo(1, &bar);         // calls the 'throwing' foo()
     foo(1, &barnothrow);  // calls the 'nothrow' foo()
   }


More information about the Digitalmars-d mailing list