zig `@ptrToInt()` "error: unable to evaluate constant expression"
zig `@ptrToInt()` "error: unable to evaluate constant expression"
我正在尝试调用 iotcl 来获取终端大小,如下所示:
const std = @import("std");
fn ioctl_TIOCGWINSZ(fd: std.os.fd_t, ws: *std.os.linux.winsize) !void {
while (true) {
switch (std.os.errno(std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @ptrToInt(ws)))) {
.SUCCESS => return,
.INTR => continue,
.INVAL => unreachable, // invalid request or argument
.BADF => unreachable, // fd is not a file descriptor
.FAULT => unreachable, // invalid argument
.NOTTY => return std.os.TermiosGetError.NotATerminal, // fd is not a tty
else => |err| return std.os.unexpectedErrno(err),
}
}
}
pub fn getTerminalSize(handle: std.os.fd_t) !type {
var size : std.os.linux.winsize = undefined;
try ioctl_TIOCGWINSZ(handle, &size);
return .{ size.ws_col, size.ws_row };
}
对 getTerminalSize
的调用是:
var size = try tz.getTerminalSize(std.os.STDOUT_FILENO);
但是,这会产生如下编译器错误:
./libs/terz/terminal.zig:40:79: error: unable to evaluate constant expression
switch (std.os.errno(std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @ptrToInt(ws)))) {
^
./libs/terz/terminal.zig:55:25: note: called from here
try ioctl_TIOCGWINSZ(handle, &size);
^
./src/main.zig:15:42: note: called from here
var size = try tz.getTerminalSize(std.os.STDOUT_FILENO);
^
./src/main.zig:5:29: note: called from here
pub fn main() anyerror!void {
^
./libs/terz/terminal.zig:40:48: note: referenced here
switch (std.os.errno(std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @ptrToInt(ws)))) {
^
./libs/terz/terminal.zig:55:25: note: referenced here
try ioctl_TIOCGWINSZ(handle, &size);
^
./src/main.zig:15:42: note: referenced here
var size = try tz.getTerminalSize(std.os.STDOUT_FILENO);
^
在std/os/linux.zig
中,ioctl
定义为:
pub fn ioctl(fd: fd_t, request: u32, arg: usize) usize {
return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), request, arg);
}
并且在 std.os.zig
中有一个功能(可能有效)类似于我正在尝试做的事情:
pub fn ioctl_SIOCGIFINDEX(fd: fd_t, ifr: *ifreq) IoCtl_SIOCGIFINDEX_Error!void {
while (true) {
switch (errno(system.ioctl(fd, SIOCGIFINDEX, @ptrToInt(ifr)))) {
.SUCCESS => return,
.INVAL => unreachable, // Bad parameters.
.NOTTY => unreachable,
.NXIO => unreachable,
.BADF => unreachable, // Always a race condition.
.FAULT => unreachable, // Bad pointer parameter.
.INTR => continue,
.IO => return error.FileSystem,
.NODEV => return error.InterfaceNotFound,
else => |err| return unexpectedErrno(err),
}
}
}
这是编译器错误,还是我做错了什么?
谢谢!
看来我的 getTerminalSize()
有一些问题,错误消息指向错误的罪魁祸首。
getTerminalSize()
不应该 returning type
。对于 return 匿名结构,语法为:
pub fn getTerminalSize(handle: std.os.fd_t) !struct{ width: u16, height: u16 } {
var size : std.os.linux.winsize = undefined;
try ioctl_TIOCGWINSZ(handle, &size);
return .{ .width = size.ws_col, .height = size.ws_row };
}
然而,zig doesn't currently support returning anonymous structs unioned with an error type.
所以目前,解决方案是命名结构:
pub const TerminalSize = struct {
width: u16,
height: u16,
};
pub fn getTerminalSize(handle: std.os.fd_t) !TerminalSize {
var size: std.os.linux.winsize = undefined;
try ioctl_TIOCGWINSZ(handle, &size);
return TerminalSize{ .width = size.ws_col, .height = size.ws_row };
}
我正在尝试调用 iotcl 来获取终端大小,如下所示:
const std = @import("std");
fn ioctl_TIOCGWINSZ(fd: std.os.fd_t, ws: *std.os.linux.winsize) !void {
while (true) {
switch (std.os.errno(std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @ptrToInt(ws)))) {
.SUCCESS => return,
.INTR => continue,
.INVAL => unreachable, // invalid request or argument
.BADF => unreachable, // fd is not a file descriptor
.FAULT => unreachable, // invalid argument
.NOTTY => return std.os.TermiosGetError.NotATerminal, // fd is not a tty
else => |err| return std.os.unexpectedErrno(err),
}
}
}
pub fn getTerminalSize(handle: std.os.fd_t) !type {
var size : std.os.linux.winsize = undefined;
try ioctl_TIOCGWINSZ(handle, &size);
return .{ size.ws_col, size.ws_row };
}
对 getTerminalSize
的调用是:
var size = try tz.getTerminalSize(std.os.STDOUT_FILENO);
但是,这会产生如下编译器错误:
./libs/terz/terminal.zig:40:79: error: unable to evaluate constant expression
switch (std.os.errno(std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @ptrToInt(ws)))) {
^
./libs/terz/terminal.zig:55:25: note: called from here
try ioctl_TIOCGWINSZ(handle, &size);
^
./src/main.zig:15:42: note: called from here
var size = try tz.getTerminalSize(std.os.STDOUT_FILENO);
^
./src/main.zig:5:29: note: called from here
pub fn main() anyerror!void {
^
./libs/terz/terminal.zig:40:48: note: referenced here
switch (std.os.errno(std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @ptrToInt(ws)))) {
^
./libs/terz/terminal.zig:55:25: note: referenced here
try ioctl_TIOCGWINSZ(handle, &size);
^
./src/main.zig:15:42: note: referenced here
var size = try tz.getTerminalSize(std.os.STDOUT_FILENO);
^
在std/os/linux.zig
中,ioctl
定义为:
pub fn ioctl(fd: fd_t, request: u32, arg: usize) usize {
return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), request, arg);
}
并且在 std.os.zig
中有一个功能(可能有效)类似于我正在尝试做的事情:
pub fn ioctl_SIOCGIFINDEX(fd: fd_t, ifr: *ifreq) IoCtl_SIOCGIFINDEX_Error!void {
while (true) {
switch (errno(system.ioctl(fd, SIOCGIFINDEX, @ptrToInt(ifr)))) {
.SUCCESS => return,
.INVAL => unreachable, // Bad parameters.
.NOTTY => unreachable,
.NXIO => unreachable,
.BADF => unreachable, // Always a race condition.
.FAULT => unreachable, // Bad pointer parameter.
.INTR => continue,
.IO => return error.FileSystem,
.NODEV => return error.InterfaceNotFound,
else => |err| return unexpectedErrno(err),
}
}
}
这是编译器错误,还是我做错了什么?
谢谢!
看来我的 getTerminalSize()
有一些问题,错误消息指向错误的罪魁祸首。
getTerminalSize()
不应该 returning type
。对于 return 匿名结构,语法为:
pub fn getTerminalSize(handle: std.os.fd_t) !struct{ width: u16, height: u16 } {
var size : std.os.linux.winsize = undefined;
try ioctl_TIOCGWINSZ(handle, &size);
return .{ .width = size.ws_col, .height = size.ws_row };
}
然而,zig doesn't currently support returning anonymous structs unioned with an error type.
所以目前,解决方案是命名结构:
pub const TerminalSize = struct {
width: u16,
height: u16,
};
pub fn getTerminalSize(handle: std.os.fd_t) !TerminalSize {
var size: std.os.linux.winsize = undefined;
try ioctl_TIOCGWINSZ(handle, &size);
return TerminalSize{ .width = size.ws_col, .height = size.ws_row };
}