Zig 将 std.os.argv 转换为 C 类型 argv

问题描述 投票:0回答:1

我有一个与 c 库 (xlib) 集成的 Zig 项目。该库有一个方法,要求我将整个 argv 数组作为参数传递给它。在 zig extern 定义中,库函数的 argv 参数的预期类型是

[*c][*c]u8

当我运行 Linux 时,我使用非跨平台方式在 zig 中获取 cli 参数

var argv = std.os.argv;

之字形参数的类型为

[][*:0]u8
。我有 2 个问题。

  1. 将 Zig vargs 转换/构建为 C vargs 的最实用方法是什么(
    [][*:0]u8
    ->
    [*c][*c]u8
  2. [*c][*c]u8
    到底是什么意思?

我已经很久没有在这么低的水平上工作了。我是否正确理解

[*c][*c]u8
是一个 c 指针列表,其中每个 c 指针都是指向以 null 结尾的字符串的第一个字符的指针?

c pointers zig
1个回答
0
投票

将 Zig vargs 转换/构建为 C vargs 的最实用方法是什么([][*:0]u8 -> [*c][*c]u8)

切片上的

@ptrCast
.ptr
属性:

const argv = std.os.argv;
const c_ptr: [*c][*c]u8 = @ptrCast(argv.ptr);

(我认为这里不需要指针强制转换 - 它应该能够隐式强制转换

argv.ptr
,但它拒绝隐式强制转换指针子项)

[*c][*c]u8 到底是什么意思?

之字形指针有点令人困惑。有具有不同选项和相似语法的指针、切片和值数组:

  • *u8
    :指向 u8 值的指针。可以取消引用 (
    value.*
    ) 但不能索引 (
    value[0]
    )
  • [*]u8
    :指向 u8 值的未知长度的多项指针。可以建立索引,但不能取消引用。
  • [*c]u8
    :一种单项或多项指针类型,仅用于 c 兼容性。它既可以被取消引用,也可以被索引。
    • 在c中,所有指针都可以取消引用和索引:
      int myvalue = 0;
      int* mypointer = &myvalue;
      *mypointer = 1; // allowed
      mypointer[0] = 2; // allowed
      
    • 将 c 转换为 zig 时,zig 不知道 c 指针是单个项还是数组。
    • 这就是它发出
      [*c]
      指针的原因,这两种用途都允许。
  • []u8
    :一个切片,它是一个指针和一个长度。它类似于
    struct {ptr: [*]u8, len: usize}
    。它可以被索引但不能取消引用。
  • [N]u8
    :值数组类型。这不是一个指针,尽管它看起来像一个。

未知长度的指针和切片可以有标记值。

[:0]u8
指定切片在最后一项 (
0
) 之后有一个
slice[slice.len] == 0
[*:0]u8
指定虽然长度未知,但数组最后一项之后的项应该是
0

常规指针和未知长度指针都可以隐式转换为 C 兼容性指针。

现在回答问题

  • [*c]
    一个或多个项目指针包含
    • [*c]
      一个或多个项目指针包含
      • u8

因为我们知道它们是数组,所以 zig 中更好的表示是

[*][*:0]u8
,数组的数组。
translate-c
不知道这一点,所以它发出 C 兼容性指针。

  • [*]
    未知长度数组指针,包含
    • [*:0]
      长度未知
      0
      -哨兵数组指针包含
      • u8

因为我们也知道外部数组的长度(带有argv),所以我们可以将指针

[*][*:0]u8
和长度
usize
组合成一个切片:
[][*:0]u8

这就是为什么

std.os.argv
返回
[][*:0]u8

© www.soinside.com 2019 - 2024. All rights reserved.