zig - 如何动态导入 zig 模块?

标签 zig

我正在使用 zig 0.7.0.我正在尝试从数组中导入 zig 源文件列表。每个源文件都有一个 main我想调用的函数(其返回类型是 !void )。数组 module_names在编译时已知。
这是我试图做的:

const std = @import("std");
const log = std.log;

const module_names = [_][]const u8{
    "01.zig", "02.zig", "03.zig", "04.zig", "05.zig",
};

pub fn main() void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();

    for (module_names) |module_name, i| {
        const module = @import(module_name); // this fails
        log.info("i {}", .{i});
        try module.main();
    }
}
即使数组在编译时已知,@import(module_name)给我这个错误:
./src/main.zig:13:32: error: unable to evaluate constant expression
        const module = @import(module_name);
                               ^
./src/main.zig:13:24: note: referenced here
        const module = @import(module_name);
如果数组是动态生成的并且只在运行时知道,我可以理解错误,但这里是 module_names数组在编译时是已知的。所以我有点迷茫...
或者,我也尝试包装整个 main正文 comptime堵塞:
pub fn main() void {
    comptime {
        var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
        defer arena.deinit();

        for (module_names) |module_name, i| {
            const module = @import(module_name); // no errors here
            log.info("i {}", .{i});
            try module.main();
        }
    }
}
这里@import(module_name)没有给我任何错误,但是 log.info因其他错误而失败:
/home/jack/.zig/lib/zig/std/mutex.zig:59:87: error: unable to evaluate constant expression
            if (@cmpxchgWeak(usize, &self.state, 0, MUTEX_LOCK, .Acquire, .Monotonic) != null)
                                                                                      ^
/home/jack/.zig/lib/zig/std/mutex.zig:65:35: note: called from here
            return self.tryAcquire() orelse {
                                  ^
/home/jack/.zig/lib/zig/std/log.zig:145:60: note: called from here
            const held = std.debug.getStderrMutex().acquire();
                                                           ^
/home/jack/.zig/lib/zig/std/log.zig:222:16: note: called from here
            log(.info, scope, format, args);
               ^
./src/main.zig:26:21: note: called from here
            log.info("i {}", .{i});
这种动态导入可以在zig中实现吗?

最佳答案

我认为您所追求的那种导入是可能的,我的理解是 @import正在服用 zig源文件并将其转换为结构类型。它实际上似乎甚至可以在运行时完成(尽管不使用 @import ,它需要一个 comptime 参数(这是您问题的重要部分)。
您的第一个示例失败的原因是您传递的参数 module_name不知道 comptime , 你的 for在您的程序运行之前,循环不会执行。
您解决问题的直觉是正确的,在编译时让循环进行评估(特别是捕获值和迭代器);我认为你可以做两件事来解决它。
将循环包裹在 comptime 中像您所做的那样阻塞将起作用,但是您需要考虑在编译时评估表达式的确切含义,以及它是否有意义。我认为 log 的执行将阻止您在编译时记录,因此您需要在循环内收集您感兴趣的值,并将它们记录在 comptime 之外。堵塞。
您可以修复它的另一种方法是通过使用 inline for 展开循环来强制在编译时评估循环的捕获值。 :

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();

    inline for (module_names) |module_name, i| {
        const module = @import(module_name);
        log.info("i {}", .{i});
        try module.main();
    }
}
免责声明:可能有更好的方法,我对语言比较陌生=D

关于zig - 如何动态导入 zig 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65157883/

相关文章:

zig - 将切片转换为数组

memory-leaks - 使用 ArrayLists 构建切片时如何避免内存泄漏

arrays - 如何创建任意大小的多维数组?

zig - 如何创建与文件大小相同的缓冲区?

zig - 仅在特定程序中将转换后的 u8(来自 i8)追加到 ArrayList 时出错

c - zig 创建一个 C 库但不能被 C 使用

zig - 为什么字符串数组需要中缀常量?

zig - 当前在 Zig 中获取用户输入的方法

zig - 如何将 C++ 标准库合并到 Zig 程序中?