簡體   English   中英

如何將 Zig String 文字傳遞給 C

[英]How can I pass a Zig String literal to C

Zig String 字面量是指向空終止字節數組的單項指針,非常適合用作 C 的char * String!

但是,當我嘗試使用來自 Zig 的這個簡單的 C function 時:

int count_bytes(const char *str) {
  int count = 0;
  while(str[count]) {
    count++;
  }
  return count;
}

Zig來電者:

const std = @import("std");
const c = @cImport({
    @cInclude("add.c");
});
const testing = std.testing;

test "should be able to count string length" {
    try testing.expectEqual(0, c.count_bytes(""));
}

我收到此錯誤:

./src/main.zig:16:46: error: expected type '[*c]u8', found '*const [0:0]u8'
    try testing.expectEqual(0, c.count_bytes(""));
                                             ^
./src/main.zig:16:46: note: cast discards const qualifier
    try testing.expectEqual(0, c.count_bytes(""));
                                             ^

This article解釋了類似情況下的Zig String文字,但我無法使用該技巧使String成為非常量:

test "should be able to count string length" {
    var cstr = "".*;
    try testing.expectEqual(0, c.count_bytes(&cstr));
}

結果是一個更奇怪的錯誤:

./src/main.zig:17:45: error: expected type 'comptime_int', found 'c_int'
    try testing.expectEqual(0, c.count_bytes(&cstr));
                                            ^

我還嘗試將 String 轉換為C 指針,如 Zig Docs 所示

test "should be able to count string length" {
    var cstr: [*c]u8 = &"".*;
    try testing.expectEqual(0, c.count_bytes(cstr));
}

這也給出了一個錯誤:

./src/main.zig:16:27: error: expected type '[*c]u8', found '*const [0:0]u8'
    var cstr: [*c]u8 = &"".*;
                          ^
./src/main.zig:16:27: note: cast discards const qualifier
    var cstr: [*c]u8 = &"".*;
                          ^

我怎樣才能做到這一點?

編輯:

我收到的建議不適用於 Zig 0.9,這是我撰寫本文時最新的穩定版本。

如果您認為自己知道解決方案,請先嘗試一下...將 C 文件放在src-c/add.c ,將 Zig 文件放在src/main.zig ,然后運行它來嘗試:

zig test src/main.zig -I src-c 

錯誤:預期類型“comptime_int”,找到“c_int”

很難看到,因為 zig 當前如何打印錯誤位置,但這個錯誤實際上是針對 expectEqual 的第二個參數,而不是 count_bytes 參數的錯誤

./src/main.zig:17:45: error: expected type 'comptime_int', found 'c_int'
    try testing.expectEqual(0, c.count_bytes(&cstr));
                                            ^

Would be slightly clearer if it was like this:
./src/main.zig:17:45: error: expected type 'comptime_int', found 'c_int'
    try testing.expectEqual(0, c.count_bytes(&cstr));
                               ~~~~~~~~~~~~~~~~~~~~

箭頭指向( ,表示它旨在覆蓋整個調用表達式

此錯誤是由於std.testing.expectEqual推斷參數類型的方式造成的。

expectEqual定義為fn expectEqual(a: anytype, b: @TypeOf(a)) void 這意味着b的類型必須與a的類型相同,並且不嘗試對等類型解析。

在這種情況下, a的類型是comptime_int因為這是 zig 中整數文字的默認類型,然后當第二個參數是無法轉換為comptime_int的運行時整數時它會出錯

為了解決這個問題,您通常需要在使用expectEqual時顯式轉換

try testing.expectEqual(@as(c_int, 0), c.count_bytes(""));

問題#4437提出了一種可能的解決方案來解決此問題,但尚未進行任何更改。

錯誤:預期類型 '[*c]u8',發現 '*const [0:0]u8'

我無法使用您提供的代碼復制此錯誤 - 頭文件是否可能錯誤地將count_bytes定義為int count_bytes(char *str)而不是int count_bytes(const char *str)

關於文檔,您傳遞的是指向 N 項 ( *[N]T ) 的指針或指向運行時已知 ( []T ) 的指針,而不是傳遞多項指針 ( [*]T ) 或單項指針( *T )。

所以使用cstr.ptr&cstr[0]應該可以工作。

test "should be able to count string length" {
    var cstr = "";
    try testing.expectEqual(0, c.count_bytes(cstr.ptr));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM