How would the equivalent C type be in D?
FeepingCreature
feepingcreature at gmail.com
Wed Mar 1 08:26:07 UTC 2023
On Wednesday, 1 March 2023 at 08:12:05 UTC, rempas wrote:
> I'm looking into
> [this](https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html) tutorial to learn XCB and I'm trying to write the code in D with betterC. In the section 9.1 (sorry, I cannot give a section link, the article does not give us this ability), I'm facing a problem and my program exits with the exit code: "-11". I suspect that this happens because I haven't translated the following code the right way:
>
> ```d
> uint32_t value[1];
> value[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> I originally tried to translate this as:
>
> ```d
> uint[1] value;
> value[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> But then, when I tried to compile the program, I got the
> following error:
>
> ```
> Error: function `headers.xcb_create_gc(xcb_connection_t* c,
> uint cid, uint drawable, uint value_mask, const(void)*
> value_list)` is not callable using argument types
> `(xcb_connection_t*, uint, uint, uint, uint[1])`
> src/draw.d(18,16): cannot pass argument `value` of type
> `uint[1]` to parameter `const(void)* value_list`
> ```
>
> So I thought of doing the following:
>
> ```d
> uint* value;
> value[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> Now the program complies but I get the "-11" exit code. Another
> thing I thought (which is probably the same thing under the
> hood but done a different way):
>
> ```d
> const(void)* value;
> (cast(ubyte*)value)[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> Same results. Any ideas?
11 is SIGSEGV. A segfault, or access violation, happens when you
try to access unallocated memory. In this case, let me annotate
your code so it's easier to see what's happening:
```d
// null is the default value for a pointer
uint* value = null;
// because `value` is null, the first index also lies at null.
assert(&value[0] is null);
// So we try to store screen.black_pixel at memory address null,
which is unallocated.
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```
As there is no memory segment allocated at address null, the CPU
indicates a segmentation fault, which terminates the program.
So yes, `xcb_create_gc` wants a `uint*` parameter, but not just
any `uint*` will do: it has to point to valid memory. Going back
to the first snippet, what's happening here is that in C, arrays
implicitly convert to pointers, because C doesn't have a notion
of array types as distinct from pointer types. So you can have a
variable declared as `uint[1]`, but pass it to a parameter that
expects `uint*`, and the value that is passed will just be the
address of the first field of the array. However, even in C, if
you try to define `value` as `uint*`, it will segfault in the
same way. Instead, in D, you need to tell the compiler to define
an array of size 1, and then pass a pointer to the array's first
member explicitly:
```d
uint32_t[1] value;
value[0] = screen.black_pixel;
// this is what C does under the hood
xcb_create_gc(connection, black, win, mask, &value[0]);
```
Or shorter, but with the same effect:
```d
uint32_t[1] value;
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value.ptr);
```
More information about the Digitalmars-d-learn
mailing list