简体   繁体   English

如何将 C 字符串传递给需要 Zig 字符串的 Zig 函数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM