扩展库 / serial

serial

系统与硬件
1.0.0C / xlang同步 I/O

Windows 与 Linux 串口设备、独立内存回环。文本和二进制接口统一按字节计数,读取结果独立拥有,短读短写保留真实传输量。C 与 xlang 共用缓冲、锁和错误合同。

验收边界:Windows / Linux 回环、并发和分配失败已验证;Linux 另通过真实内核 PTY 的双向 I/O、超时、断线、配置及 C/xlang 对照。USB/物理串口、热拔插和驱动差异仍未验收,不能把 PTY 结果等同硬件发布认证。当前完整 AOT 门禁受编译器缺符号阻断。

快速开始

回环不需要硬件
import serial
from serial import Serial

func main(...) as int
    Serial port = serial.openLoopback(115200)
    port.setTimeouts(1500, 1000)
    assert port.write("你好") == 6
    println(port.read(6))

    Buffer bytes = Buffer()
    assert bytes.appendByte(0) and bytes.appendByte(255)
    assert port.writeBytes(bytes) == 2
    Buffer result = port.readBytes(2)
    assert result.byteAt(0) == 0 and result.byteAt(1) == 255
    return 0
end

连接 Windows 设备使用 serial.open("COM3", 115200),Linux 使用 serial.open("/dev/ttyUSB0", 115200) 或稳定的 /dev/serial/by-id/... 路径。程序必须有设备权限;对象自动释放句柄。Linux 打开时启用原始模式与内核支持的独占标志。

xlang API

入口返回 / 约定
serial.open(string port, int baudrate = 9600)Serial;默认 8 数据位、1 停止位、无校验。无效参数或含 NUL 的端口名抛 ValueError;设备失败抛 IOError。
serial.openLoopback(int baudrate = 9600)Serial;创建独立的 4096 字节内存回环队列。
Serial(port, baudrate, databits, stopbits, parity)完整构造;5..8 数据位,1/2 停止位,校验为 0 无 / 1 奇 / 2 偶。含 NUL 的端口名抛 ValueError,设备打开失败抛相应异常。
valid / isOpenbool;是否持有句柄,不是设备健康或拔线检测。
port / baudratestring / int;创建时的设备名与波特率。
availableint;当前可读字节数,失败抛 IOError。并发下只是快照。
write(string data)int;完整写入 UTF-8 字节,包括内嵌 NUL;返回实际写入数。
writeBytes(Buffer data)int;实际写入二进制字节数,不修改或接管输入。
read(int maxLen = 1024)string;将本次读取转成文本,maxLen 是字节数。
readBytes(int maxLen = 1024)独立拥有的 Buffer;负数抛 ValueError,0 不消费数据。
setTimeouts(int readMs, int writeMs)设备读写等待上限为 0..60000 毫秒;0 请求不等待,Windows 写入映射为最短 1ms 驱动超时。回环口始终立即收发。
flush()丢弃收发队列;不等待数据发送完成。失败抛 IOError。

构造和读写失败均会抛出异常。C 的 open、读写、available、flush 和 setTimeouts 以本次 XRT 错误为准;成功不保留上次失败的诊断。close、纯查询和错误读取不清掉待处理诊断。类中的 *Native 方法仅供包装层内部使用;XLang 应用使用上表的检查型方法,C 应用可直接使用公开 C API。

I/O 与拥有权约定

C 关闭句柄前,必须结束所有使用该句柄的操作。close(NULL) 安全;重复关闭、关闭后使用和并发关闭不属于有效调用。xlang 赋值或传参保留对象引用,不复制串口资源。

C API

公开头文件为 extlibs/serial/include/serial.h。编译 serial_native.c 并链接一份 XRT,无需链接 xlang 编译器。失败详情通过当前线程的 xrtGetError() 读取。

函数合同
xserial_open(name, baudrate, databits, stopbits, parity)拥有型 void*;失败 NULL。数值参数为 int64_t。
xserial_close(handle)消费句柄,恰好关闭一次。
xserial_is_open(handle)bool;NULL 为 false,不验证悬空指针。
xserial_set_timeouts(handle, readMs, writeMs)bool;0..60000 毫秒。失败时保留原配置。
xserial_write(handle, const void* data, size_t size)int64_t 实际字节数,失败 -1;只读借用输入。
xserial_write_text(handle, const char* text)按 C 字符串的 UTF-8 字节长度写入,失败 -1。
xserial_write_text_len(handle, const char* text, size_t size)显式长度的文本字节写入;允许内嵌 NUL,行为与 write 相同。
xserial_write_bytes(handle, void* data, size_t size)xlang point 的精确 ABI 入口;行为与 write 相同。
xserial_read(handle, int64_t maxBytes)返回 void*,实际为拥有型 xbuffer*;用 xrtBufferDestroy 释放。NULL 只表示失败。
xserial_available(handle)int64_t;失败 -1。
xserial_flush(handle)bool;清空队列,失败 false。
xserial_get_baudrate(handle)int64_t;NULL 为 0。
xserial_get_port(handle)借用字符串,保持到 close;NULL 返回空字符串。
xserial_error()借用当前线程错误文本,保持到错误槽变化;无错误为空字符串。

以返回值判断本次 C 操作,不要把之前的 last-error 当成新操作的失败。记录或处理错误后使用 XRT 清理接口;错误槽在线程之间隔离。

范例与验证

发行目录中,两份范例可以直接运行,13 行输出逐字一致:

xl run examples/extlibs/serial.xl
xl run examples/extlibs/serial_c.c

设备范例 extlibs/serial/examples/device_c.c 可直接用 xl build 或 xl run;运行时需提供串口路径。Linux 门禁使用独立 PTY 核对请求与响应,Windows 无设备门禁只验证构建。

源码仓库根目录下的专用门禁:

powershell -NoProfile -ExecutionPolicy Bypass -File tools/check_extlib_serial.ps1 -SkipAot
powershell -NoProfile -ExecutionPolicy Bypass -File tools/check_extlib_serial.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tools/run_platform_extlibs.ps1 -Package serial

真实设备与热拔插尚未验证,不能以回环测试代替。分配故障注入在独立 C 进程执行,不改变正在运行的 xl.dll 宿主分配策略。