#How to convert from *[]const u8 to [*c]const [*c]const u8

1 messages ยท Page 1 of 1 (latest)

sinful gale
#

Hello amazing people,
I am reading a GLSL file and I need to pass it to openGL. I have the content of that file as a []const u8, how do I turn it into a [*c]const[*c]const u8?
Thank you very much for the help!

merry sluice
#
var c_src = [_][*:0]const u8{src.ptr};
var c_len = [_]i32{ @intCast(i32, src.len) };
c.glShaderSource(shad, 1, &c_src, &c_len);
#

(or just use zgl which handles this for you :)

sinful gale
#

I will definitely use zgl, but there is something I want to explore while learning zig. So it is not a final product, is something I want to struggle with while learning zig ๐Ÿ˜„

frigid brook
#

There is no need to put everything into an array as both pointer to arrays and single item pointers can coerce to c pointers.
Here is how I would do it:

const source_len = @intCast(c_int, source.len);
c.glShaderSource(shader, 1, &source.ptr, &source_len);
sinful gale
#

Thank you both very much! I did not know single item pointers can coerce to c pointers.

#

Is there some nice schema of some sort of mappings between zig and c?

merry sluice
#

And no, you don't need to put it in arrays, but it's good practice since what OpenGL is expecting is a multi-pointer, not a single-pointer

#

While C doesn't have a distinction between those, Zig does, so it's nice to have it be the correct types on the Zig side rather than relying on C's unsafe conversions :)

sinful gale
#

Kind of agree with you both, is it weird?

#

๐Ÿ˜…

merry sluice
#

They're both fine ways to do it, as long as you understand what's going on :)

#

I prefer the explicitness of arrays since it also allows you to provide more than one source string if you want to, which is what the API is designed to do

sinful gale
#

Exactly why I love the two different approaches

sinful gale
#

Thank you both!

#
error: expected type '[*:0]const u8', found '[*]const u8'
        var c_src = [_][*:0]const u8{file_vertex.data.ptr};
#

the :0 is the termination right?

fresh scarab
#

just change the array decl to be [_][*]const u8

#

in this case you don't need null termination, because you're also passing the length

sinful gale
#

ah right, so no need for the termination!

#

thanks

fresh scarab
#

though, you may still want to consider ensuring you're using null terminated strings in the general case, in case you ever don't pass a length for whatever reason

#

but that can be a bridge crossed another time

sinful gale
#

I marked it down in my Todo list and learning list. In the end I definitely want to both understand and compile, but in that order.

fresh scarab
#

well, just as a brief: ensuring null termination can be in done in a number of ways.

The most primitive way is to just assert that a sequence of bytes is null terminated, and ask the type system to make it so, by doing slice[0.. :0]. This will panic in safe modes if slice doesn't end with 0, and is UB in unsafe modes.

The former is usually only done after an operation that creates or modifies slice, such that it would be null-terminated. E.g., reallocating the slice with an added 0 at the end, and then sentinel-slicing it.

The most frequently-used method is to use a function that does the former two for you, e.g. std.mem.Allocator.dupeZ

merry sluice
#

oops yeah, forgot this case doesn't need null termination :)

sinful gale
#

Thank you so much for the infos