[英]How to pass a C string into a Zig function expecting a Zig string?
Trying to use a Zig library expecting a string... but I get a string buffer from a C library.尝试使用需要字符串的 Zig 库...但我从 C 库中获得了字符串缓冲区。
That means that I need to pass a value of type [*c]u8
to a function that accepts [:0]const u8
.这意味着我需要将
[*c]u8
类型的值传递给接受[:0]const u8
的函数。
How to do that?怎么做?
I found this way so far:到目前为止,我发现了这种方式:
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??).哪个看起来比它应该的更复杂(并制作副本??)。
The Zig docs says that: Zig 文档说:
String literals are const pointers to null-terminated arrays of u8.
字符串字面量是指向 u8 的以 null 结尾的数组的 const 指针。
So I thought they are compatible C strings and a very simple cast like @as([*:0]const u8, buffer)
should suffice?所以我认为它们是兼容的 C 字符串,并且像
@as([*:0]const u8, buffer)
这样的非常简单的转换就足够了?
Which looks more complicated than it should (and makes a copy??).
哪个看起来比它应该的更复杂(并制作副本??)。
So I thought they are compatible C strings and a very simple cast like @as([*:0]const u8, buffer) should suffice?
所以我认为它们是兼容的 C 字符串,并且像 @as([*:0]const u8, buffer) 这样的非常简单的转换就足够了?
The issue here is that there is a difference between [*:0]u8
and [:0]u8
这里的问题是
[*:0]u8
和[:0]u8
之间存在差异
[*:0]u8
is a pointer with an unknown size ending in a 0
. [*:0]u8
是一个以0
结尾的未知大小的指针。 To determine its length, you have to loop over it and find where it ends.[:0]u8
is a slice containing a pointer and a length. [:0]u8
是一个包含指针和长度的切片。 You can think of it like struct {ptr: [*:0]u8, len: usize}
.struct {ptr: [*:0]u8, len: usize}
。 This allows code using it to immediately know its length without having to loop over it. @pointerCast
is not required to convert from a [*c]u8
to a [*:0]u8
: @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;
}
To get a zig-style string slice ( []const u8
or [:0]const u8
), you can use the standard library function std.mem.span (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
does not make a copy of the string - no standard library function will make a copy of something unless you pass it an allocator. std.mem.span
不会复制字符串 - 没有标准库函数会复制某些内容,除非您将其传递给分配器。
What it does is counts the length of the string and then returns a slice of the same memory, this time including a length.它所做的是计算字符串的长度,然后返回相同内存的切片,这次包括长度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.