#What's the best way to cast array to C pointer?

1 messages · Page 1 of 1 (latest)

steel kraken
#

Currently, I have to do something like this: @ptrCast([*c][*c]const u8, &some_cstr_array), which is very tedious to write. Is there some way to do the same with less typing?

tardy pine
#

Why do you want to do this?

steel kraken
#

Because C api takes pointer

tardy pine
#

You can pass eg. *[16][*:0]const u8 to a function that accepts [*c][*c]const u8

#

It'll implicitly coerce

steel kraken
#

Let me try to understand this syntax...

tardy pine
#

Firstly what type is your array?

steel kraken
#

It's const char**, so in my case [16]*const u8

tardy pine
#

Is that the type you've written in Zig?

#

Because if it's an array of C strings, that's not the correct type

steel kraken
#

const char** is the C type I am trying to target

tardy pine
#

*const u8 points to a single u8, not a sequence of u8

steel kraken
#

I am not sure what Zig type I should use

tardy pine
steel kraken
#

But [16]*const u8 should point to 16 C strings, right?

tardy pine
#

No, it's an array of 16 pointers to singular u8

#

You should use [16][*:0]const u8 for 16 pointers to 0-terminated sequences of u8 (which is what a C string is)

steel kraken
#

It says error: expected type '[*c][*c]const u8', found '[16][*:0]const u8'

tardy pine
#

You need to ref it, you're currently passing the array itself rather than a pointer to it

steel kraken
#

Then I get error: expected type '[*c][*c]const u8', found '*[16][*:0]const u8' instead

tardy pine
#

hmm, that should work

steel kraken
#

If you want to look at a bigger snippet:

        var n_exts: c_uint = undefined;
        var extensions: [16][*:0]const u8 = undefined;
        if (c.SDL_Vulkan_GetInstanceExtensions(window, &n_exts, &extensions) != c.SDL_TRUE) {
            @panic("Failed to get required extensions");
        }
tardy pine
#

Ohh ofc, the error note explains the issue

#

Because it's a mutable pointer type, the function could modify the array and add null pointers

#

So it has to be a [16]?[*:0]const u8

steel kraken
#

Nope: error: expected type '*[*:0]const u8', found '*[16]?[*:0]const u8'

tardy pine
#

That's erroring in a different place

#

What code is it erroring on now?

steel kraken
#
src/renderer.zig:32:49: error: expected type '*[*:0]const u8', found '*[16]?[*:0]const u8'
        const instance = try VkInstance(n_exts, &extensions);
#

Right, it's a different place

tardy pine
#

btw functions shouldn't start with capital letters in Zig :)

#

(unless they return types)

steel kraken
#

Hmmm, I thought Zig style guide says if it returns a type it should be TitleCase

tardy pine
#

Sure, but that function doesn't

steel kraken
#

It's a constructor?

tardy pine
#

It returns a vk.Instance I would assume

tardy pine
steel kraken
#

Wait, do you mean returning a "type" not an "instance"?

tardy pine
#

Yes

#

I mean if the return type is literally type

#

(which is how generics work in Zig :)

steel kraken
#

Are there any good explanation of pointer types in Zig?

#

BTW, [*c] is a bit awkward to type

#

Is it required? Or can it be implicitly cast in some case?

tardy pine
#

You almost never need to write [*c] in your own code

#

It's designed for use by translate-c and nothing else

steel kraken
#

So what should this function definition be without [*c]?

#

fn createVkInstance(n_exts: c_uint, exts: [*c][*c]const u8) !c.VkInstance

#

I tried quite a few variations of arrays and pointers, but none compile

tardy pine
#

fn createVkInstance(n_exts: c_uint, exts: [*][*:0]const u8) !c.VkInstance (assuming it can't put null pointers into exts)

steel kraken
#

Ah, I got this one to work [*]?[*:0]const u8

tardy pine
#

But if you're writing a nice Zig wrapper, use fn createVkInstance(exts: [][*:0]const u8) !c.VkInstance

#

If it can put nulls in exts then []?[*:0]const u8

steel kraken
#

OK... []?[*:0]const u8 doesn't work

#

Is there any way to remove the nullable?

tardy pine
tardy pine
steel kraken
#

It doesn't type check

#

I can check [*]?[*:0]const u8, though

tardy pine
#

But what is the error?

#

The reason I suggest []?[*:0]const u8 is because it gets rid of the extra n_exts arg

#

But it needs some tweaks inside the function

steel kraken
#
/opt/homebrew/Cellar/zig/HEAD-06e9b2c_1/lib/zig/std/mem.zig:461:65: error: expected type '[*c]const [*c]const u8', found '[]?[*:0]const u8'
                                    @field(value, field.name) = @field(init, field.name);
tardy pine
#

Yeah, it's not a pointer type

#

It's a slice, which stores pointer and len

#

So you do exts.ptr to get the pointer, and @intCast(c_uint, exts.len) to get the length

steel kraken
#

Ah, I see

#

Hmm, it gives error about getting usize despite the int cast

#

Nevermind, I put it at the wrong field

#

One last thing. Does n_ext actually capture n_ext, or will it be 16?