如何将C字符串传递给期望Zig字符串的Zig函数?

7

尝试使用期望字符串的Zig库...但我从C库获取了一个字符串缓冲区。

这意味着我需要向接受[:0]const u8的函数传递类型为[*c]u8的值。

怎么做?

到目前为止,我找到了这种方法:

const buffer: [*c]u8 = callC();
const str = std.mem.span(@ptrCast([*:0]const u8, buffer));

这看起来比应该更复杂(而且还要复制??)。

Zig文档中提到:

字符串文字是指向以null结尾的u8数组的const指针。

所以我认为它们与C字符串兼容,一个非常简单的转换,如@as([*:0]const u8, buffer)就足够了?


我可能错了,但是:@ptrCast([*:0]const u8, buffer) 应该就足够了。但是为什么要使用指针,当你可以使用美妙的切片呢?然后只需要 std.mem.span(buffer) - sigod
1个回答

9
这看起来比它应该的要复杂(并且会复制?)。因此,我认为它们是兼容的C字符串,一个非常简单的转换如@as([*:0]const u8, buffer)就足够了?
问题在于[*:0]u8和[:0]u8之间存在差异:
- [*:0]u8是以0结尾的未知大小的指针。要确定其长度,您必须循环查找其结束位置。 - [:0]u8是包含指针和长度的切片。您可以将其视为struct {ptr: [*:0]u8, len: usize}。这使得使用它的代码能够立即知道它的长度,而无需循环遍历。
@pointerCast不需要将[*c]u8转换为[*: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;
}

为了获得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");
}

const buffer: [*c]u8 = callC();
const str = std.mem.span(@ptrCast([*:0]const u8, buffer));

Which looks more complicated than it should (and makes a copy??).

std.mem.span不会复制字符串 - 除非你传递一个分配器,否则没有标准库函数会复制任何东西。

它所做的是计算字符串的长度,然后返回同一内存的切片,这次包括一个长度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接