Zig:核心:入口、日志与任务
core.zig:Zig 绑定的握手、槽位关卡、字符串、日志、任务、事件、命令和跨模组通道。
Zig 直接调用宿主的函数指针,中间没有生成的那一层:slot("name") 就是那个槽位的函数指针,经过契约第 10 节的两道检查,这里的其他函数都建立在它之上。
函数
slot
| Zig |
|---|
| pub fn slot(comptime name: []const u8) @FieldType(c.PierApi, name)
|
名为 name 的槽位的函数指针;宿主的表太短、放不下这个槽位,或者槽位为 NULL 时返回 null。abi.h 的每一个槽位都可以这样取到。
- 参数:
- name :
comptime []const u8
- 返回值类型:
@FieldType(c.PierApi, name)
handle
| Zig |
|---|
| pub fn handle() c.PierModHandle
|
调用方自己的模组句柄,供需要它的槽位使用。
str
| Zig |
|---|
| pub fn str(text: []const u8) c.PierStr
|
把 Zig 切片当作 PierStr;宿主只在调用期间读取它。
view
| Zig |
|---|
| pub fn view(s: c.PierStr) []const u8
|
把 PierStr 当作切片,只在收到它的那次回调期间有效。
log
| Zig |
|---|
| pub fn log(level: Level, msg: []const u8) void
|
通过这个模组的 LeviLamina 日志器写一行。可以在任何线程调用。
- 参数:
- level :
Level
- msg :
[]const u8
- 返回值类型:
void
- 对应槽位:
log
logf
| Zig |
|---|
| pub fn logf(level: Level, comptime fmt: []const u8, args: anytype) void
|
用 std.fmt 格式化的 log,写进一个 2048 字节的缓冲区。
- 参数:
- level :
Level
- fmt :
comptime []const u8
- args :
anytype
- 返回值类型:
void
- 对应槽位:
log
exportMod
| Zig |
|---|
| pub fn exportMod(comptime M: type, comptime name: []const u8) void
|
为模组类型 M 导出 pier_main,在日志里以 name 命名。在根文件里调用:
| Zig |
|---|
| comptime { levilamina.exportMod(MyMod, "my-mod"); }
|
M 可以声明 pub fn load、enable、disable 和 unload 中的任意几个,每个都接收 *levilamina.Context,返回 !void;返回错误时会记录日志,并拒绝这一步。
- 参数:
- M :
comptime type
- name :
comptime []const u8
- 返回值类型:
void
- 对应槽位:
log
schedule
| Zig |
|---|
| pub fn schedule(comptime task: fn () void) Error!TaskId
|
尽快在服务器线程上运行 task。可以在任何线程调用。任务属于这个模组:模组先卸载的话,宿主会丢掉这个任务,它永远不会运行。
- 参数:
- task :
comptime fn () void
- 返回值类型:
Error!TaskId
- 对应槽位:
schedule_for
scheduleAfter
| Zig |
|---|
| pub fn scheduleAfter(delay_ms: u64, comptime task: fn () void) Error!TaskId
|
在 delay_ms 毫秒后于服务器线程上运行 task,归属规则和 schedule 一样。
cancel
| Zig |
|---|
| pub fn cancel(id: TaskId) Error!bool
|
作废一个还没运行的任务;已经运行过、已经取消过,或者不属于这个模组的任务返回 false。
pendingTasks
| Zig |
|---|
| pub fn pendingTasks() Error!u32
|
这个模组还没运行的任务数。宿主数不出来时返回错误。
声明
c
| Zig |
|---|
| pub const c = @import("abi");
|
translate-c 从 abi.h 读出来的 ABI:所有的类型、槽位和常量。
TaskId
任务 id,供 cancel 使用。
Collector
| Zig |
|---|
| pub const Collector = struct {
allocator: std.mem.Allocator,
items: std.ArrayList([]u8) = .empty,
failed: bool = false,
// ...
};
|
收集一次调用期间 PierStrSink 收到的内容,每一段都用 allocator 复制一份。
Collector.init
| Zig |
|---|
| pub fn init(allocator: std.mem.Allocator) Collector
|
- 参数:
- allocator :
std.mem.Allocator
- 返回值类型:
Collector
Collector.deinit
| Zig |
|---|
| pub fn deinit(self: *Collector) void
|
Collector.sink
| Zig |
|---|
| pub fn sink(ctx: ?*anyopaque, s: c.PierStr) callconv(.c) void
|
交给宿主的 PierStrSink,ctx 是一个 *Collector。
- 参数:
- ctx :
?*anyopaque
- s :
c.PierStr
- 返回值类型:
callconv(.c) void
Collector.take
| Zig |
|---|
| pub fn take(self: *Collector) Error![]u8
|
最后一段,归调用方所有;输出回调什么都没收到时返回 NoAnswer。
Collector.takeOrEmpty
| Zig |
|---|
| pub fn takeOrEmpty(self: *Collector) Error![]u8
|
最后一段;输出回调什么都没收到时,返回一个归调用方所有的空切片。
Collector.takeAll
| Zig |
|---|
| pub fn takeAll(self: *Collector) Error![][]u8
|
所有的段,连同装着它们的切片,都归调用方所有。
Context
| Zig |
|---|
| pub const Context = struct { ... };
|
生命周期的每一步收到的东西。
Context.info
| Zig |
|---|
| pub fn info(_: *Context, msg: []const u8) void
|
- 参数:
- _ :
*Context
- msg :
[]const u8
- 返回值类型:
void
- 对应槽位:
log
Context.warn
| Zig |
|---|
| pub fn warn(_: *Context, msg: []const u8) void
|
- 参数:
- _ :
*Context
- msg :
[]const u8
- 返回值类型:
void
- 对应槽位:
log
Context.err
| Zig |
|---|
| pub fn err(_: *Context, msg: []const u8) void
|
- 参数:
- _ :
*Context
- msg :
[]const u8
- 返回值类型:
void
- 对应槽位:
log
Error
| Zig |
|---|
| pub const Error = error{
/// The host has no such slot: it is older than this binding or lacks the capability.
NotProvided,
/// The host ran the call and refused it.
Refused,
/// The host has no answer for the read.
NoAnswer,
OutOfMemory,
};
|
调用失败的原因。宿主答不上来的读取返回 NoAnswer。
Level
| Zig |
|---|
| pub const Level = enum(i32) {
fatal = 0, err = 1, warn = 2, info = 3, debug = 4, trace = 5
};
|
log 槽位的日志级别,对应 ll::io::LogLevel。