![](/img/trans.png)
[英]How to legally use type-punning with unions to cast between variations of struct sockaddr without violating the strict aliasing rule?
[英]How to allocate a struct of incomplete type in Zig?
我想在 Zig 中使用 POSIX 正則表達式例程,但我不知道如何分配模式緩沖區 ( regex_t
)。 我認為問題在於它被定義為typedef struct re_pattern_buffer regex_t
(在我的情況下,在 GNU 系統上),因此 Zig 無法判斷它有多大。
在一個標准的zig init-exe
項目(今天的 Zig master)中,我有以下main.zig
:
const std = @import("std");
const c = @cImport({@cInclude("regex.h");});
pub fn main() anyerror!void {
var re: c.regex_t = undefined;
std.log.info("address of re {}", .{re});
}
在其他默認的build.zig
中,我添加了一行exe.linkLibC();
.
然后, zig build
給出以下錯誤:
./src/main.zig:5:5: error: variable of type '.cimport:2:11.struct_re_pattern_buffer' not allowed
var re: c.regex_t = undefined;
^
這很公平,但我無法弄清楚我應該做什么! 我可以看到一些潛在的解決方法:
struct re_pattern_buffer
; 但這不是可移植的,因為它不是 POSIX 標准的一部分(盡管至少 musl 和 glibc 將它用作regex_t
的底層結構)。malloc
並返回regex_t
的 C 函數,然后使用它。 應該沒問題,因為所有 POSIX API 都采用regex_t *
,所以如果只需要處理指針,Zig 就不需要知道regex_t
有多大。但是,如果沒有這些變通辦法中的任何一種,那就太好了。 有什么提示嗎?
struct_re_pattern_buffer
被定義為opaque {};
在 c 導入源中
// found by adding `--verbose-cimport` to the zig build
pub const struct_re_pattern_buffer = opaque {};
pub const regex_t = struct_re_pattern_buffer;
在 C 頭文件中,它被定義為
struct re_pattern_buffer
{
… // http://hte.sourceforge.net/doxygenized-0.8.0pre1/structre__pattern__buffer.html
};
typedef struct re_pattern_buffer regex_t;
它無法正確翻譯結構的原因是 zig 尚未處理 cimported 結構中的位域( #1499 )。 它通常應該在 cimport 文件中顯示錯誤,但由於某種原因這次不是:
pub const struct_re_dfa_t = opaque {}; // (no file):28:1: warning: struct demoted to opaque type - has bitfield
直接使用struct re_pattern_buffer; 但這不是可移植的,因為它不是 POSIX 標准的一部分(盡管至少 musl 和 glibc 將它用作 regex_t 的底層結構)。
這將不起作用,因為由於位域,zig 根本無法翻譯結構。
編寫一個 malloc 並返回 regex_t 的 C 函數,並使用它。 應該沒問題,因為所有 POSIX API 都采用 regex_t *,所以 Zig 不需要知道 regex_t 有多大,如果它只需要處理指針。
這將起作用,並且通常是任何 cimport 問題的最簡單的解決方法。
regex_t* alloc_regex_t(void);
void free_regex_t(regex_t* ptr);
如果您想使用 zig 分配器分配它,解決方法非常復雜:
要分配它,您需要知道它的大小。 你可以:
// header:
#include <stdint.h>
size_t my_sizeof_regex_t();
uint16_t my_alignof_regex_t();
// source:
#include <stdint.h>
#include <stdalign.h>
#include <regex.h>
size_t my_sizeof_regex_t() {
return sizeof(regex_t);
}
uint16_t my_alignof_regex_t() {
return alignof(regex_t);
}
在 zig 中,將其分配到指定了自定義對齊方式的字節數組中。
var re_zig_slice = try allocator.allocBytes(
c.my_alignof_regex_t(),
c.my_sizeof_regex_t(),
0,
@returnAddress(),
);
var re = @ptrCast(*c.regex_t, re_zig_slice.ptr);
defer try allocator.rawFree(@ptrCast([*]u8, re)[0..c.my_sizeof_regex_t()]), c.my_alignof_regex_t, @returnAddress());
這變得更加復雜,因為在 zig 中,分配器在分配和釋放時需要知道對象的大小和對齊方式。 C 的 malloc 在內部存儲大小以便正確釋放,並且始終對它分配的所有內容使用單個對齊值。
注意:或者,如果您使用 c abi 中結構的最大對齊方式進行對齊,並且在釋放它之前使用@alignCast
指針 @alignCast ,則可以使用普通allocWithOptions
和free
方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.