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)

Reply via email to