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.

Reply via email to