尝试使用需要字符串的 Zig 库...但我从 C 库获得了字符串缓冲区。
这意味着我需要将类型值传递[*c]u8给接受[:0]const u8.
怎么做?
到目前为止我发现了这种方法:
const buffer: [*c]u8 = callC();
const str = std.mem.span(@ptrCast([*:0]const u8, buffer));
Run Code Online (Sandbox Code Playgroud)
这看起来比应有的更复杂(并且制作了副本??)。
Zig 文档说:
字符串文字是指向 u8 的以 null 结尾的数组的 const 指针。
所以我认为它们是兼容的 C 字符串,并且像这样的非常简单的转换@as([*:0]const u8, buffer)就足够了?
pfg*_*pfg 12
这看起来比应有的更复杂(并且制作了副本??)。
所以我认为它们是兼容的 C 字符串,并且像 @as([*:0]const u8, buffer) 这样的非常简单的转换应该足够了?
[*:0]u8这里的问题是和之间存在差异[:0]u8
[*:0]u8是一个大小未知、以 a 结尾的指针0。要确定它的长度,您必须遍历它并找到它的结束位置。[:0]u8是一个包含指针和长度的切片。你可以这样想struct {ptr: [*:0]u8, len: usize}。这允许使用它的代码立即知道它的长度,而不必循环它。@pointerCast不需要从 a 转换[*c]u8为 a [*:0]u8:
const std = @import("std");
test "convert c string to [*:0]u8" {
const c_string: [*c]const u8 = "some c string";
const as_ptr: [*:0]const u8 = c_string;
_ = as_ptr;
}
Run Code Online (Sandbox Code Playgroud)
要获得 Zig 样式的字符串切片([]const u8或[:0]const u8),可以使用标准库函数std.mem.span (ptr):
const std = @import("std");
test "convert c string to zig string" {
const c_string: [*c]const u8 = "some c string";
const as_slice: [:0]const u8 = std.mem.span(c_string);
try std.testing.expectEqualStrings(as_slice, "some c string");
}
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)const buffer: [*c]u8 = callC(); const str = std.mem.span(@ptrCast([*:0]const u8, buffer));这看起来比应有的更复杂(并且制作了副本??)。
std.mem.span不复制字符串 - 没有标准库函数会复制某些内容,除非您将其传递给分配器。
它的作用是计算字符串的长度,然后返回同一内存的一个切片,这次包括一个长度。