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