[英]How to pass a C string into a Zig function expecting a Zig string?
[英]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.