Request assistance initializing struct instance at global scope

Andrew Edwards edwards.ac at gmail.com
Tue Dec 8 02:45:09 UTC 2020


On 12/7/20 10:56 PM, Adam D. Ruppe wrote:
> On Monday, 7 December 2020 at 04:13:16 UTC, Andrew Edwards wrote:
>> Given:
>>
>> ===============
>> extern(C):
>> char*[] hldr;
> 
> Why is this extern(C)? A D array ere is probably wrong.

To stay as close to the original implementation as possible. This will 
all change when the entire code base compiles in D.

> In C, a `char*[] hldr = {...}` is actually represented in D as a static 
> length array, like `char*[1] = [null];`

Thanks. Because I was having issues I didn't know how to resolve, I 
actually defined it as `string ft` instead and passed around `ft.ptr` 
when calling

> It should also generally be __gshared if it was declared in C (C 
> defaults to global, D defaults to thread-local), and if declared in C, 
> an additional extern may be required.
> 

Noted. I'll keep that in mind when trying to link to C in the future.

> 
> So, if you are trying to *link* to C code that has this:
> 

I'm porting it. All of the code is available from the D source file.

> 
> You'd bind to it in D with
> 
> ---
> // D
> extern(C) extern __gshared char*[1] hldr; // matches the C. Make sure 
> the length matches too

Ok, got it.

> S[] s = [S(cast(char*) "c", &hldr[0])]; // that cast is super iffy 
> though. Should S have `const(char)* ft` instead?
> 

Probably. I just did a direct port. They had char* so I just kept it 
that way. I'll change it to string once the initial port is complete. 
But I'll remember that when I come across it in the future.

> 
> In that thing:
> 
> extern(C) - tells it it has a C name.
> extern - tells it the actual variable is declared externally. This 
> second one makes the linker pull the variable's address from the C code 
> instead of declaring a new variable in D that can be used from C.
> __gshared - turn off D's thread local default to match C's global.
> 

Learning has occurred. Thanks.

> 
> Now if you are translating C code to D, that might be different, 
> certainly the second extern is wrong then, and you need to copy over the 
> initial value but the rest still works:

This.

> ```
> // no more second extern, D is now creating a new variable, then it 
> needs to know the value too
> extern(C) __gshared char*[1] hldr = [null];

Okay. I'll need to be mindful of this in the future. But to resolve the 
issue this time around, I just used a string[] since that's the end 
state anyway.

> // rest is the same
> // including
> S[] s = [S(cast(char*) "c", &hldr[0])]; // since it is a gshared static 
> array, this still works
> ```

Yup... got this to compile with main() and static this() in the correct 
location.

> 
> But there's a few other contexts that might change this, then you 
> probably do want the static constructor, or maybe you can make some 
> things immutable and make it work that way. All depends on a bit more 
> information than your code gives on its own....

Thanks for the lesson... I've learned quite a lot.


More information about the Digitalmars-d-learn mailing list