On Tuesday, 15 March 2016 at 18:47:22 UTC, Adam D. Ruppe wrote:
Like you would another D library.
Now I get it! Yes, that works as expected.
The problem isn't the struct itself, but the D initializer.
Structs in C don't have initalizers but do in D:
struct Foo {
int a = 10; /* illegal in C, legal in D */
};
Note that extern(C) doesn't actually do anything on a struct,
it really only applies to functions and global variables.
That's where I got it wrong!
D realizes this by creating a variable called
_DStructName__init which has the initial value of the struct.
When you make a variable of that type, it copies the value of
this hidden init thing over to your new variable to initialize
it. C does nothing of the sort, so the C library will not
provide this - you need to link in the one from D.
You might be thinking "but I don't use = anything in this
struct", but there's a few places where D will put one in
automatically:
float and double = NaN by default
char, wchar, and dchar = -1 (well, 0xff) by default
And everything else =0 (or null) by default.
If *everything* in a struct is initialized to 0, the __init
variable is left out and memset(&struct, struct.sizeof, 0) is
called instead.
But if *anything* in there is non-zero, the __init variable is
created and referenced when you declare the variable (unless
you =void it at the usage point).
Which causes the undefined reference problem you're seeing -
the usage code is trying to initialize, but the C library
doesn't provide that (since it isn't a C feature) and the D
library isn't linked in.
Thanks a million! Now I understand why it didn't work with my
implementation.
[snip]