Closed mleise closed 7 years ago
call D code internally
Would this include any C function that takes a function pointer, as it could be passed a D function (marked with extern(C)) that allocates or throws?
@rcorre you can mark functions/delegates as nothrow.
alias myFunc = extern(C) void function() nothrow;
Any function being passed to or is a c function declaration should really be nothrow @system @nogc
. After all c code won't be calling our GC, throwing our exceptions and is most definitely not safe.
So marking a such a C function as @nogc nothrow
would prevent passing any function that isn't also @nogc nothrow
, which is generally a 'good thing'? Would the passed function have to be explicitly marked as such or can it be implied (i.e. could it break existing code)?
There are two separate cases going on here:
1)
extern(C)
void cFunc() nothrow @system @nogc;
2)
alias ACFunc = extern(C) void function() nothrow @system @nogc;
extern(C)
void cFunc(ACFunc arg) nothrow @system @nogc;
So in the first case is the same as defining a function in C and exporting it for access via shared library loading, but it won't accept any arguments that are functions.
In the second case we pass in a function to a C function. Keep in mind both the C function as well as the argument must be declared as being extern(C)
as well as nothrow @system @nogc
.
After all, our exceptions and GC collecting won't work from within C code and good chance it'll end in a segfault.
The only attribute that can be not included in this is @nogc as long as you know what the C code is doing and in most cases its fine.
I've experienced such segfaults first hand some time ago with GtkD. My D code threw an exception inside C code and druntime tried to unwind the stack. To do so it looks at the frame pointer register, but all my C libraries are compiled without explicit frame pointer. So druntime misinterpreted the register for a stack frame and crashed when dereferencing it. This request here doesn't have to do with that though. I'd just like to use Allegro5 in code marked @nogc and thought I should put a "reminder" somewhere.
If they don't call D code internally, C functions should be marked
extern(C) nothrow @nogc { … }
.