#C string to Zig slice
1 messages · Page 1 of 1 (latest)
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,
^~~~~~~~~~
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);
}
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
if ptr points to more than one item, the better type to use would be [*]c_char or [*]u8, and if you know it to have a null terminator, then [*:0]c_char or [*:0]u8 (from the perspective of the C ABI, these are all equivalent)
with the latter two, you can convert it to a slice by just calling std.mem.span(ptr)
It's a callback function to be used in C calling convention tho
the thread is titled "C string to Zig slice" though. You don't want a Zig slice?
all those pointers work fine with the C ABI, the extra info is only relevant to Zig
I see, thanks you pointing that out :)
Yes I do
also, just fyi, you should avoid manually writing code that uses [*c]: https://github.com/ziglang/zig/issues/2984
To be honest, I dont really understand what [*c] is lol
[*] is a pointer to many
but the c idk
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
Ohhh
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
the lang ref is really good about pointers, it's just written like a reference so takes some disgestion.
https://ziglang.org/documentation/0.13.0/#C-Pointers
vs. the table of normal pointers: https://ziglang.org/documentation/0.13.0/#Pointers
the pointer types definitely take some gettting used to but are nice once you can read/understand them
yes, initially very off-putting and then welcomed. Like a lot of Zig for me.
Ahaha, yes, I jsut started re-learning Zig and doing the ziglings and slowly getting used to Zigs way of things too :)
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
Im trying to set some background for advent of code this year