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]

Reply via email to