#C string to Zig slice

1 messages · Page 1 of 1 (latest)

cyan lark
#

Hello, I have a *c_char that points to a C string (a sequence of chars that end with \0). It represents a JSON object that I want to use in the std.json.parseFromSlice, but that takes in a Slice, and not a C string!

How do I convert to a Slice? Is it possible?

#

I tried this but I got error:

fn write_callback(ptr: *c_char, size: usize, nmemb: usize, userdata: *anyopaque) callconv(.C) usize {
    const data: *CurrentWeather = @alignCast(@ptrCast(userdata));
    const response: [*c]const u8 = @ptrCast(ptr);

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer _ = gpa.deinit();

    const parsed = try std.json.parseFromSlice(
        CurrentWeather,
        allocator,
        response[0.. :0], // Error
        .{},
    );

    data.* = parsed.value;
    return size * nmemb;
}
#
install
└─ install meteoz
   └─ zig build-exe meteoz Debug native 2 errors
src/openweather.zig:112:17: error: expected type '[]const u8', found '[*c]const u8'
        response[0.. :0],
        ~~~~~~~~^~~~~~~~
/Users/juacu7340/.zig/lib/std/json/static.zig:76:8: note: parameter type declared here
    s: []const u8,
       ^~~~~~~~~~
dark sky
#
const std = @import("std");

test "slice it" {
    const s1: [*c]const u8 = "hello";
    const s2: []const u8 = s1[0..5];
    const s3: []const u8 = s1[0..std.mem.len(s1)];
    try std.testing.expectEqualStrings(s2, "hello");
    try std.testing.expectEqualStrings(s2, s3);
}
cyan lark
#

Oh!

#

Why did my way not work?

dark sky
#

I didn't know that [0..:0] syntax even exists, but what it yields is a *const[10:0]u8

#

well actually,

test "where is this documented?" {
    const s1: [*c]const u8 = "hello";
    const s2 = s1[0..5 :0];
    @compileLog(s2); // @as(*const [5:0]u8, "hello")
    const s3: []const u8 = s1[0..5 :0];
    @compileLog(s3); // @as([]const u8, "hello"[0..5])
}
#

probably just doesn't infer how you want

#

Sentinel-terminated slices can also be created using a variation of the slice syntax data[start..end :x], where data is a many-item pointer, array or slice and x is the sentinel value.

#

ok, so that's generated sentinel-termianted slices and they're just coercing to different values in my example. Kinda weird. You don't want that anyway because you want a slice, not a sentinel-terminated slice

little ether
cyan lark
#

It's a callback function to be used in C calling convention tho

dark sky
#

the thread is titled "C string to Zig slice" though. You don't want a Zig slice?

little ether
#

all those pointers work fine with the C ABI, the extra info is only relevant to Zig

cyan lark
little ether
cyan lark
#

To be honest, I dont really understand what [*c] is lol

#

[*] is a pointer to many

#

but the c idk

little ether
#

it's basically "a pointer to anything", could be a single item, many items, sentinel terminated, etc; in other words, it's a c-style pointer

cyan lark
#

Ohhh

little ether
#

Zig has more specific pointer types that are still just pointers at runtime but have more (compile-time only) information about what they point to

dark sky
little ether
#

the pointer types definitely take some gettting used to but are nice once you can read/understand them

dark sky
#

yes, initially very off-putting and then welcomed. Like a lot of Zig for me.

cyan lark
#

Ahaha, yes, I jsut started re-learning Zig and doing the ziglings and slowly getting used to Zigs way of things too :)

dark sky
#

big points with [*c] are

Coerces to other pointer types, as well as Optional Pointers. When a C pointer is coerced to a non-optional pointer, safety-checked Undefined Behavior occurs if the address is 0.
Allows address 0.
so if you have them you can get rid of them fast with a coercion. Just mind null

cyan lark
#

Im trying to set some background for advent of code this year