Access to structures defined in C

Adam D. Ruppe destructionator at gmail.com
Wed Mar 14 02:17:57 UTC 2018


On Wednesday, 14 March 2018 at 01:58:24 UTC, Joe wrote:
> The C header of course declares this as:
>
> extern char *files[];
>
> The way to declare it in a D module appears to be:
>
> extern (C) {
>    __gshared extern char *[] files;
> }


A D array[] should *almost never* be used in extern(C). (tbh I'm 
almost of the opinion that it should be an error, but since it is 
almost never instead of never ehhhh)


Anyway, D `array[]` is a structure consisting of a length and 
pointer combo.

C `array[]` is one of two things: a D `array[N]` with static 
size, or a D `array*`, a pointer.

In function parameters, it is... I'm pretty sure... always a 
pointer. So even

void foo(char* item[4]);

in C becomes

extern(C) foo(char** item);

in D.



BUT, for a global array in C, it is frequently going to be a 
static length array in D. So

char *files[] = { "one", "two", "three", 0};

is

extern(C) __gshared extern char*[4] files;


in D. Why? The C array variable is actually a block of memory 
rather than a pointer. And in D, that's represented as an 
array[N] with a specific size. So that's what we have here.


BTW the exact length isn't super important for an extern here. 
The type system would *like* to know, certainly for correct range 
errors, but if you declare it as the wrong length and use the 
.ptr, it still works like it does in C:

extern(C) __gshared extern char*[1] files; // still works

import core.stdc.stdio;

void main() {
         printf("%s\n", files.ptr[2]); // ptr bypasses the range 
check
}


But if you can match the length, that's ideal. BTW remember D 
static arrays are passed by value if assigned around; they will 
be copied. So use the .ptr if you want to  use the pointer of it 
like it is in C (notably, when passing that array to other C 
functions, remember, C function params are still pointers)


More information about the Digitalmars-d-learn mailing list