ffi

    ffi
    native
    syscall
    sys
    libc
    Download zip
    Author
    Version
    0.2.5
    License
    Apache-2.0
    Last updated
    10 hours ago
    Downloads
    31

    #moonbit-ffi

    MoonBit 的底层 C FFI 绑定。纯声明,无抽象。

    #安装

    moon add Qisu-dev/ffi

    #功能

    模块内容
    memorymalloc calloc realloc free
    memmemcpy memmove memset memcmp
    ptris_null null_ptr ptr_add bytes_as_ptr fixed_array_as_ptr
    strstrlen strcmp strcpy strdup bytes_to_cstr cstr_to_string
    errnoerrno_get errno_set strerror enoent eacces 等
    fileopen close read write lseek pipe dup
    mmapmmap munmap(POSIX)、create_file_mapping map_view_of_file unmap_view_of_file(Windows)

    #示例

    #内存与文件

    fn main {
    // 分配内存
    let buf = @ffi.malloc(1024)
    if @ffi.is_null(buf) { return }
    defer @ffi.free(buf)

    // 写文件
    let cpath = @ffi.string_to_cstr("out.txt")
    defer @ffi.free(cpath)
    let fd = @ffi.open(cpath, @ffi.o_wronly() | @ffi.o_creat(), 0o644)
    defer { @ffi.close(fd); () }
    @ffi.write(fd, @ffi.bytes_as_ptr(b"hello"), 5)

    // 错误处理
    if fd < 0 {
    let err = @ffi.errno_get()
    println(@ffi.cstr_to_string(@ffi.strerror(err)))
    }
    }

    #内存映射读文件

    #cfg(not(platform="windows"))
    fn mmap_read(name : String) -> Unit raise {
    let cpath = @ffi.string_to_cstr(name)
    defer @ffi.free(cpath)

    let fd = @ffi.open(cpath, @ffi.o_rdonly(), 0)
    if fd < 0 { raise Failure("open failed") }
    defer { @ffi.close(fd); () }

    let fstate = @ffi.fstat(fd)
    if @ffi.is_null(fstate) { raise Failure("fstat failed") }
    defer @ffi.free(fstate)

    let size = @ffi.fstat_size(fstate).reinterpret_as_uint64()
    if size == 0 { return }

    let addr = @ffi.mmap(
    @ffi.null_ptr(), size,
    @ffi.prot_read(), @ffi.map_private(),
    fd, 0,
    )
    if addr == @ffi.map_failed() {
    raise Failure("mmap failed")
    }
    defer ignore(@ffi.munmap(addr, size))

    // addr 是只读的连续内存,可直接处理
    ignore(addr)
    }

    #注意

    • mmap 失败返回 MAP_FAILED,用 == @ffi.map_failed() 判断,不是 is_null
    • Windows 下 map_view_of_file 失败返回 NULL,用 is_null 判断
    • bytes_as_ptr 返回的指针在 Bytes 释放后悬垂
    • 指针偏移后不能 free,只能 free 原始指针
    • 仅支持 native 后端(Windows / Linux / macOS)

    平台状态
    Windows✅ 已验证, 可以使用
    Linux⚠️ 代码已写,未在真实环境验证
    macOS⚠️ 代码已写,未在真实环境验证

    #License

    Apache-2.0

    SizeT

    type SizeT = UInt64

    FFIPtr

    #external
    pub(all) type FFIPtr

    abort

    fn abort() -> Unit

    异常终止当前进程。

    不会执行任何清理:
    • 不调用 atexit
    • 不刷新 FILE* 缓冲
    • 触发 SIGABRT,可能产生 core dump

    用于不可恢复的错误。

    atof

    fn atof(s : FFIPtr) -> Double

    ⚠️ 无错误检测。推荐用 strtod。

    atoi

    fn atoi(s : FFIPtr) -> Int

    ⚠️ 无错误检测。推荐用 strtol。

    atol

    fn atol(s : FFIPtr) -> Int64

    ⚠️ 无错误检测。推荐用 strtol。

    bytes_as_ptr

    fn bytes_as_ptr(bytes : Bytes) -> FFIPtr

    注意, 这个指针在Bytes死亡后会悬空

    bytes_to_cstr

    fn bytes_to_cstr(data : Bytes, len : UInt64) -> FFIPtr

    calloc

    fn calloc(count : UInt64, size : UInt64) -> FFIPtr

    chdir

    fn chdir(path : FFIPtr) -> Int

    切换当前工作目录到 path。

    参数:
    • path:目标目录路径(C 字符串)。

    返回:
    • 成功:0。
    • 失败:-1(errno 记录原因,如 ENOENT、EACCES)。

    注意:
    • 影响后续所有相对路径的解析。
    • 只改变当前进程的工作目录,不影响其他进程。

    clearerr

    fn clearerr(stream : FFIPtr) -> Unit

    清除 EOF 标志和错误标志。

    close

    fn close(fd : Int) -> Int

    关闭文件描述符。

    cstr_to_string

    fn cstr_to_string(s : FFIPtr) -> String

    dup

    fn dup(fd : Int) -> Int

    复制文件描述符(POSIX)。

    dup2

    fn dup2(oldfd : Int, newfd : Int) -> Int

    复制到指定文件描述符(POSIX)。

    e2big

    fn e2big() -> Int

    E2BIG (7) — 参数列表过长。

    eacces

    fn eacces() -> Int

    EACCES (13) — 权限不足。

    文件存在但无访问权限。

    eaddrinuse

    fn eaddrinuse() -> Int

    EADDRINUSE (100) — 地址已使用。

    绑定的端口已被占用。

    eaddrnotavail

    fn eaddrnotavail() -> Int

    EADDRNOTAVAIL (101) — 地址不可用。

    eafnosupport

    fn eafnosupport() -> Int

    EAFNOSUPPORT (102) — 地址族不支持。

    eagain

    fn eagain() -> Int

    EAGAIN (11) — 资源暂时不可用。

    非阻塞 I/O 时数据未就绪,需重试。

    ealready

    fn ealready() -> Int

    EALREADY (103) — 操作已在进行。

    ebadf

    fn ebadf() -> Int

    EBADF (9) — 错误的文件描述符。

    fd 无效或未打开。

    ebadmsg

    fn ebadmsg() -> Int

    EBADMSG (104) — 错误消息。

    ebusy

    fn ebusy() -> Int

    EBUSY (16) — 资源忙。

    设备或文件被占用。

    ecanceled

    fn ecanceled() -> Int

    ECANCELED (105) — 操作已取消。

    echild

    fn echild() -> Int

    ECHILD (10) — 无子进程。

    econnaborted

    fn econnaborted() -> Int

    ECONNABORTED (106) — 连接中止。

    econnrefused

    fn econnrefused() -> Int

    ECONNREFUSED (107) — 连接被拒绝。

    目标端口无监听。

    econnreset

    fn econnreset() -> Int

    ECONNRESET (108) — 连接被重置。

    edeadlk

    fn edeadlk() -> Int

    EDEADLK (36) — 资源死锁。

    避免死锁时可能发生。

    edestaddrreq

    fn edestaddrreq() -> Int

    EDESTADDRREQ (109) — 需要目标地址。

    edom

    fn edom() -> Int

    EDOM (33) — 数学参数超出定义域。

    eexist

    fn eexist() -> Int

    EEXIST (17) — 文件已存在。

    O_CREAT | O_EXCL 时常见。

    efault

    fn efault() -> Int

    EFAULT (14) — 地址错误。

    传入了无效的内存地址。

    efbig

    fn efbig() -> Int

    EFBIG (27) — 文件过大。

    超过文件系统或进程允许的最大文件大小。

    ehostunreach

    fn ehostunreach() -> Int

    EHOSTUNREACH (110) — 主机不可达。

    eidrm

    fn eidrm() -> Int

    EIDRM (111) — 标识符已移除。

    eilseq

    fn eilseq() -> Int

    EILSEQ (42) — 非法字节序列。

    字符编码转换时遇到无效字节。

    einprogress

    fn einprogress() -> Int

    EINPROGRESS (112) — 操作在进行中。

    非阻塞 connect 尚未完成。

    eintr

    fn eintr() -> Int

    EINTR (4) — 系统调用被信号中断。

    通常需要重试。

    einval

    fn einval() -> Int

    EINVAL (22) — 参数非法。

    eio

    fn eio() -> Int

    EIO (5) — I/O 错误。

    底层硬件或驱动错误。

    eisconn

    fn eisconn() -> Int

    EISCONN (113) — 已连接。

    eisdir

    fn eisdir() -> Int

    EISDIR (21) — 是目录。

    试图以文件方式打开目录。

    eloop

    fn eloop() -> Int

    ELOOP (114) — 符号链接层数过多。

    emfile

    fn emfile() -> Int

    EMFILE (24) — 进程打开文件过多。

    达到进程级 fd 上限。
    fn emlink() -> Int

    EMLINK (31) — 链接过多。

    超过文件系统的硬链接数上限。

    emsgsize

    fn emsgsize() -> Int

    EMSGSIZE (115) — 消息过长。

    enametoolong

    fn enametoolong() -> Int

    ENAMETOOLONG (38) — 文件名过长。

    enetdown

    fn enetdown() -> Int

    ENETDOWN (116) — 网络已关闭。

    enetreset

    fn enetreset() -> Int

    ENETRESET (117) — 网络连接被重置。

    enetunreach

    fn enetunreach() -> Int

    ENETUNREACH (118) — 网络不可达。

    enfile

    fn enfile() -> Int

    ENFILE (23) — 系统打开文件过多。

    达到系统级 fd 上限。

    enobufs

    fn enobufs() -> Int

    ENOBUFS (119) — 缓冲区空间不足。

    enodata

    fn enodata() -> Int

    ENODATA (120) — 无数据。

    enodev

    fn enodev() -> Int

    ENODEV (19) — 无此设备。

    enoent

    fn enoent() -> Int

    ENOENT (2) — 文件或目录不存在。

    enoexec

    fn enoexec() -> Int

    ENOEXEC (8) — 执行格式错误。

    文件不是有效的可执行格式。

    enolck

    fn enolck() -> Int

    ENOLCK (39) — 无可用锁。

    系统锁表已满。
    fn enolink() -> Int

    ENOLINK (121) — 链接已断开。

    enomem

    fn enomem() -> Int

    ENOMEM (12) — 内存不足。

    malloc 失败时常见。

    enomsg

    fn enomsg() -> Int

    ENOMSG (122) — 无消息。

    enoprotoopt

    fn enoprotoopt() -> Int

    ENOPROTOOPT (123) — 协议选项不可用。

    enospc

    fn enospc() -> Int

    ENOSPC (28) — 磁盘空间不足。

    enosr

    fn enosr() -> Int

    ENOSR (124) — 流资源不足。

    enostr

    fn enostr() -> Int

    ENOSTR (125) — 非流。

    enosys

    fn enosys() -> Int

    ENOSYS (40) — 功能未实现。

    系统调用未实现。

    enotconn

    fn enotconn() -> Int

    ENOTCONN (126) — 未连接。

    enotdir

    fn enotdir() -> Int

    ENOTDIR (20) — 非目录。

    路径中某一段不是目录。

    enotempty

    fn enotempty() -> Int

    ENOTEMPTY (41) — 目录非空。

    enotrecoverable

    fn enotrecoverable() -> Int

    ENOTRECOVERABLE (127) — 状态不可恢复。

    enotsock

    fn enotsock() -> Int

    ENOTSOCK (128) — 非套接字。

    对非 socket fd 调用 socket 操作。

    enotsup

    fn enotsup() -> Int

    ENOTSUP (129) — 不支持。

    enotty

    fn enotty() -> Int

    ENOTTY (25) — 非法 I/O 控制操作。

    ioctl 不适用于该设备。

    enxio

    fn enxio() -> Int

    ENXIO (6) — 无此设备或地址。

    eopnotsupp

    fn eopnotsupp() -> Int

    EOPNOTSUPP (130) — 操作不支持。

    eother

    fn eother() -> Int

    EOTHER (131) — 其他错误(MSVC 特有)。

    eoverflow

    fn eoverflow() -> Int

    EOVERFLOW (132) — 值过大。

    超出目标类型可表示范围。

    eownerdead

    fn eownerdead() -> Int

    EOWNERDEAD (133) — 所有者已死。

    eperm

    fn eperm() -> Int

    EPERM (1) — 操作不允许。

    调用者没有执行该操作所需的权限。

    epipe

    fn epipe() -> Int

    EPIPE (32) — 管道破裂。

    向已关闭读端的管道写入。

    eproto

    fn eproto() -> Int

    EPROTO (134) — 协议错误。

    eprotonosupport

    fn eprotonosupport() -> Int

    EPROTONOSUPPORT (135) — 协议不支持。

    eprototype

    fn eprototype() -> Int

    EPROTOTYPE (136) — 协议类型错误。

    erange

    fn erange() -> Int

    ERANGE (34) — 结果超出范围。

    数学函数结果超出可表示范围。

    erofs

    fn erofs() -> Int

    EROFS (30) — 只读文件系统。

    espipe

    fn espipe() -> Int

    ESPIPE (29) — 非法 seek。

    对管道、socket 等不可定位的流调用 lseek。

    esrch

    fn esrch() -> Int

    ESRCH (3) — 无此进程。

    找不到指定的进程 ID。

    etime

    fn etime() -> Int

    ETIME (137) — 定时器过期。

    etimedout

    fn etimedout() -> Int

    ETIMEDOUT (138) — 超时。

    etxtbsy

    fn etxtbsy() -> Int

    ETXTBSY (139) — 文本文件忙。

    试图修改正在执行的可执行文件。

    ewouldblock

    fn ewouldblock() -> Int

    EWOULDBLOCK (140) — 操作会阻塞。

    某些系统上等同于 EAGAIN。

    exdev

    fn exdev() -> Int

    EXDEV (18) — 跨设备链接。

    试图在不同文件系统间创建硬链接。

    exit

    fn exit(code : Int) -> Unit

    终止当前进程,退出码为 code。

    会执行以下清理:
    • 调用 atexit 注册的函数
    • 刷新所有 FILE* 流的缓冲区
    • 关闭所有打开的流

    退出码约定:0 表示成功,非 0 表示失败。

    fclose

    fn fclose(stream : FFIPtr) -> Int

    关闭文件流,自动刷新缓冲区。

    成功返回 0,失败返回 -1。

    fdopen

    fn fdopen(fd : Int, mode : FFIPtr) -> FFIPtr

    用已有的 fd 创建 FILE*。

    • fd:已打开的文件描述符
    • mode:模式字符串(同 fopen)

    成功返回 FILE*,失败返回 NULL。

    ⚠️ fdopen 之后 FILE* 接管 fd,不要再直接用 fd。 fclose 会关闭底层的 fd。

    feof

    fn feof(stream : FFIPtr) -> Int

    判断是否到达文件末尾。

    返回非 0 表示 EOF,0 表示未到。

    ⚠️ EOF 标志是"粘性"的——只有 clearerr 或 rewind 能清除。 判断前先读取,读完后才能判断。

    ferror

    fn ferror(stream : FFIPtr) -> Int

    判断流是否发生了错误。

    返回非 0 表示有错误,0 表示无。

    fflush

    fn fflush(stream : FFIPtr) -> Int

    强制刷新缓冲区,把数据写到内核。

    成功返回 0,失败返回 -1。

    用途:实时输出、崩溃前保留日志、交互式程序。

    fileno

    fn fileno(stream : FFIPtr) -> Int

    从 FILE* 提取底层 fd。

    失败返回 -1。

    ⚠️ 不要混用 fread/fwrite(缓冲)和 read/write(无缓冲)—— 缓冲会导致数据错位。

    fixed_array_as_ptr

    fn fixed_array_as_ptr(array : FixedArray[Byte]) -> FFIPtr

    注意, 这个指针在fixed array死亡后会悬空

    fopen

    fn fopen(path : FFIPtr, mode : FFIPtr) -> FFIPtr

    打开文件流。

    • path:文件路径(C 字符串)
    • mode:打开模式("r"、"w"、"a"、"rb"、"wb" 等)

    成功返回 FILE*,失败返回 NULL(errno 记录原因)。

    fread

    fn fread(buf : FFIPtr, size : UInt64, count : UInt64, stream : FFIPtr) -> UInt64

    从流读取 count 个元素,每个 size 字节。

    返回实际读取的元素个数(不是字节数)。

    ⚠️ 返回值可能是 count,也可能更少。配合 feof/ferror 判断原因。 常用 size=1 让返回值直接等于字节数。

    free

    fn free(size : FFIPtr) -> Unit

    fseek

    fn fseek(stream : FFIPtr, offset : Int64, whence : Int) -> Int

    移动文件读写位置。

    • offset:相对 whence 的偏移量(字节)
    • whence:基准位置(seek_set()/seek_cur()/seek_end())

    成功返回 0,失败返回非 0。

    ⚠️ 不支持管道、socket、终端等不可定位的流。

    fstat

    fn fstat(fd : Int) -> FFIPtr

    获取已打开文件的元数据。

    内部 malloc 一个 struct stat 并调用 fstat 填充。

    返回:
    • 成功:指向 struct stat 的指针。
    • 失败:NULL(用 is_null 判断,errno 记录原因)。

    ⚠️ 用完必须 stat_free 释放。

    fstat_atime

    fn fstat_atime(st : FFIPtr) -> Int64

    最后访问时间(Unix 时间戳,秒)。

    fstat_ctime

    fn fstat_ctime(st : FFIPtr) -> Int64

    状态改变时间(Unix 时间戳,秒)。

    fstat_is_dir

    fn fstat_is_dir(st : FFIPtr) -> Int

    是否目录。返回 1 是,0 否。

    fstat_is_regular

    fn fstat_is_regular(st : FFIPtr) -> Int

    是否普通文件。返回 1 是,0 否。

    fstat_mode

    fn fstat_mode(st : FFIPtr) -> Int

    权限位(POSIX mode)。

    fstat_mtime

    fn fstat_mtime(st : FFIPtr) -> Int64

    最后修改时间(Unix 时间戳,秒)。

    fstat_size

    fn fstat_size(st : FFIPtr) -> Int64

    文件大小(字节)。

    ftell

    fn ftell(stream : FFIPtr) -> Int64

    获取当前读写位置(相对文件开头)。

    返回字节偏移,失败返回 -1。

    fwrite

    fn fwrite(buf : FFIPtr, size : UInt64, count : UInt64, stream : FFIPtr) -> UInt64

    向流写入 count 个元素,每个 size 字节。

    返回实际写入的元素个数。

    ⚠️ 返回值 < count 表示写入不完整或出错。 常用 size=1 让返回值直接等于字节数。

    get_errno

    fn get_errno() -> Int

    获取当前线程的 errno 值。

    系统调用失败后立即读取,得到具体错误码。

    get_stderr

    fn get_stderr() -> FFIPtr

    获取 stderr 的 FILE*。

    get_stdin

    fn get_stdin() -> FFIPtr

    获取 stdin 的 FILE*。

    get_stdout

    fn get_stdout() -> FFIPtr

    获取 stdout 的 FILE*。

    getcwd

    fn getcwd(buf : FFIPtr, size : UInt64) -> FFIPtr

    获取当前工作目录。

    参数:
    • buf:接收路径的缓冲区(至少 size 字节)。
    • size:缓冲区大小。

    返回:
    • 成功:buf(指向填充好的缓冲区)。
    • 失败:NULL(用 is_null() 判断,errno 记录原因)。

    注意:
    • 如果路径长度 ≥ size,返回 NULL 并设置 errno = ERANGE。
    • 建议缓冲区至少 4096 字节(PATH_MAX 的常见值)。
    • 返回的路径不带尾部斜杠(根目录除外)。

    getenv

    fn getenv(name : FFIPtr) -> FFIPtr

    获取环境变量的值。

    参数:
    • name:环境变量名(C 字符串)。

    返回:
    • 成功:指向变量值的指针(不要 free,由环境表管理)。
    • 不存在:NULL(用 is_null() 判断)。

    注意:
    • 返回的指针在后续 setenv/unsetenv 后可能失效。
    • 不要修改返回的字符串。

    getpid

    fn getpid() -> Int

    获取当前进程 ID。

    返回: 当前进程的 PID(正整数)。

    getppid

    fn getppid() -> Int

    获取父进程 ID(仅 POSIX)。

    返回: 父进程的 PID。

    注意: Windows 没有此函数。Windows 用户调用会编译错误。

    is_null

    fn is_null(ptr : FFIPtr) -> Bool

    lseek

    fn lseek(fd : Int, offset : Int64, whence : Int) -> Int64

    移动文件偏移量。返回新偏移(-1 = 错误)。

    malloc

    fn malloc(size : UInt64) -> FFIPtr

    map_anonymous

    fn map_anonymous() -> Int

    MAP_ANONYMOUS — 匿名映射(不关联文件,fd 传 -1)。

    map_failed

    fn map_failed() -> FFIPtr

    POSIX mmap 的失败返回值 MAP_FAILED,即 (void*)-1。

    ⚠️ 这不是 NULL!判断 mmap 是否失败要用 == map_failed(),不能用 is_null()。

    map_private

    fn map_private() -> Int

    MAP_PRIVATE — 私有映射(写时复制)。

    map_shared

    fn map_shared() -> Int

    MAP_SHARED — 共享映射(写入影响原文件)。

    memccpy

    fn memccpy(dst : FFIPtr, src : FFIPtr, c : Int, n : UInt64) -> FFIPtr

    拷贝直到遇到字符 c 或拷满 n 字节。返回指向 c 后一个字节的指针,或 NULL。

    memcmp

    fn memcmp(dst : FFIPtr, src : FFIPtr, size : UInt64) -> Int

    memcpy

    fn memcpy(dst : FFIPtr, src : FFIPtr, size : UInt64) -> Unit

    memmove

    fn memmove(dst : FFIPtr, src : FFIPtr, size : UInt64) -> Unit

    memset

    fn memset(ptr : FFIPtr, value : Int, size : UInt64) -> Unit

    mmap

    fn mmap(addr : FFIPtr, len : UInt64, prot : Int, flags : Int, fd : Int, offset : Int64) -> FFIPtr

    将文件或匿名内存映射到进程地址空间。

    参数:
    • addr:建议的映射起始地址。
      • 传 null_ptr() → 由系统选择合适地址(推荐)。
      • 传具体地址 → 系统尽量满足,但可能忽略。
    • len:要映射的字节数。
      • 匿名映射:分配的字节数。
      • 文件映射:映射的文件区间长度。
    • prot:内存保护属性,描述访问权限。
      • prot_read():可读。
      • prot_write():可写。
      • prot_exec():可执行。
      • prot_none():不可访问。
      • 可用 | 组合,如 prot_read() | prot_write()。
    • flags:映射标志,决定映射类型和行为。
      • map_shared():共享映射,写入影响原文件。
      • map_private():私有映射,写时复制(COW)。
      • map_anonymous():匿名映射,不关联文件(fd 传 -1)。
      • 必须指定 map_shared() 或 map_private() 之一。
    • fd:文件描述符。
      • 文件映射:open() 返回的有效 fd。
      • 匿名映射:传 -1(同时 flags 必须含 map_anonymous())。
    • offset:文件偏移量。
      • 必须页对齐(通常是 4096 的倍数)。
      • 匿名映射:传 0。

    返回:
    • 成功:映射区域的起始地址。
    • 失败:MAP_FAILED(即 (void*)-1,用 == map_failed() 判断,不是 is_null())。

    注意:
    • 映射后可用指针直接读写文件内容,无需 read/write。
    • 使用完毕必须调用 munmap(addr, len) 解除映射。
    • map_shared() 的写入会同步到文件,map_private() 的写入不会。

    munmap

    fn munmap(addr : FFIPtr, len : UInt64) -> Int

    解除内存映射。成功返回 0,失败返回 -1。

    null_ptr

    fn null_ptr() -> FFIPtr

    o_append

    fn o_append() -> Int

    O_APPEND — 追加模式

    o_creat

    fn o_creat() -> Int

    O_CREAT — 文件不存在时创建

    o_excl

    fn o_excl() -> Int

    O_EXCL — 与 O_CREAT 配合,文件已存在则失败

    o_nonblock

    fn o_nonblock() -> Int

    O_NONBLOCK 标志(POSIX)。

    o_rdonly

    fn o_rdonly() -> Int

    O_RDONLY — 只读打开

    o_rdwr

    fn o_rdwr() -> Int

    O_RDWR — 读写打开

    o_trunc

    fn o_trunc() -> Int

    O_TRUNC — 截断为 0 长度

    o_wronly

    fn o_wronly() -> Int

    O_WRONLY — 只写打开

    open

    fn open(path : FFIPtr, flags : Int, mode : Int) -> Int

    打开文件,返回文件描述符(失败返回 -1)。

    pipe

    fn pipe(fds : FixedArray[Int]) -> Int

    创建管道(POSIX)。fds 长度为 2,fds[0] 读端,fds[1] 写端。

    prot_exec

    fn prot_exec() -> Int

    PROT_EXEC — 页面可执行。

    prot_none

    fn prot_none() -> Int

    PROT_NONE — 页面不可访问。

    prot_read

    fn prot_read() -> Int

    PROT_READ — 页面可读。

    prot_write

    fn prot_write() -> Int

    PROT_WRITE — 页面可写。

    ptr_add

    fn ptr_add(ptr : FFIPtr, offset : Int64) -> FFIPtr

    ptr_to_cstr

    fn ptr_to_cstr(data : FFIPtr, len : UInt64) -> FFIPtr

    read

    fn read(fd : Int, buf : FFIPtr, count : UInt64) -> Int64

    从文件描述符读取。返回读取字节数(0 = EOF,-1 = 错误)。

    realloc

    fn realloc(ptr : FFIPtr, size : UInt64) -> FFIPtr

    rewind

    fn rewind(stream : FFIPtr) -> Unit

    把位置移到文件开头,并清除错误标志。

    seek_cur

    fn seek_cur() -> Int

    SEEK_CUR — 从当前位置偏移

    seek_end

    fn seek_end() -> Int

    SEEK_END — 从文件末尾偏移

    seek_set

    fn seek_set() -> Int

    SEEK_SET — 从文件开头偏移

    set_errno

    fn set_errno(value : Int) -> Unit

    设置当前线程的 errno 值。

    用于清除(设为 0)或在错误后恢复。

    setenv

    fn setenv(name : FFIPtr, value : FFIPtr, overwrite : Int) -> Int

    设置环境变量。

    参数:
    • name:变量名。
    • value:变量值。
    • overwrite:非 0 则覆盖已存在的变量,0 则不覆盖。

    返回:
    • 成功:0。
    • 失败:-1(errno 记录原因)。

    注意: Windows 上 overwrite 参数被忽略,总是覆盖。

    stderr_fd

    fn stderr_fd() -> Int

    标准错误 fd(2)

    stdin_fd

    fn stdin_fd() -> Int

    标准输入 fd(0)

    stdout_fd

    fn stdout_fd() -> Int

    标准输出 fd(1)

    strcat

    #deprecated("此函数并不安全, 不推荐使用")
    fn strcat(dst : FFIPtr, src : FFIPtr) -> Unit

    ⚠️ 不安全:不检查 dst 大小,可能溢出。

    strchr

    fn strchr(s : FFIPtr, c : Int) -> FFIPtr

    查找第一个字符 c

    strcmp

    fn strcmp(a : FFIPtr, b : FFIPtr) -> Int

    按字典序比较两个 C 字符串。返回 <0、=0、>0

    strcpy

    fn strcpy(dst : FFIPtr, src : FFIPtr) -> Unit

    ⚠️ 不安全:不检查 dst 大小,可能溢出

    strcspn

    fn strcspn(s : FFIPtr, reject : FFIPtr) -> UInt64

    从开头算起,连续不属于 reject 字符集的字符个数

    strdup

    fn strdup(s : FFIPtr) -> FFIPtr

    strerror

    fn strerror(errnum : Int) -> FFIPtr

    将 errno 转为人类可读的字符串。

    返回的指针指向静态缓冲区,不要 free,也不要长期持有。

    string_to_cstr

    fn string_to_cstr(s : String) -> FFIPtr

    注意: 用完后应当free cstr

    strlen

    fn strlen(s : FFIPtr) -> UInt64

    计算 C 字符串长度(不含 \0)

    strncat

    fn strncat(dst : FFIPtr, src : FFIPtr, n : UInt64) -> Unit

    拼接最多 n 个字符,保证 \0 结尾。

    strncmp

    fn strncmp(a : FFIPtr, b : FFIPtr, n : UInt64) -> Int

    比较前 n 个字符

    strncpy

    fn strncpy(dst : FFIPtr, src : FFIPtr, n : UInt64) -> Unit

    ⚠️ 半安全:限制长度,但可能不补 \0 结尾。 此函数并非不可使用而是极其易错 如果你想继续使用 如下示例
    let cstr_ptr = bytes_to_cstr(b"hello", 5)
    defer free_cstr(cstr_ptr)
    let dst = malloc(6)
    defer free(dst)
    strncpy(dst, cstr_ptr, 5)
    memset(ptr_add(dst, 5), 0, 1)

    strndup

    fn strndup(s : FFIPtr, n : UInt64) -> FFIPtr

    strnlen

    fn strnlen(s : FFIPtr, maxlen : UInt64) -> UInt64

    计算 C 字符串长度,最多检查 maxlen 个字节

    strpbrk

    fn strpbrk(s : FFIPtr, accept : FFIPtr) -> FFIPtr

    查找 accept 中任意字符的首次出现

    strrchr

    fn strrchr(s : FFIPtr, c : Int) -> FFIPtr

    查找最后一个字符 c

    strspn

    fn strspn(s : FFIPtr, accept : FFIPtr) -> UInt64

    从开头算起,连续属于 accept 字符集的字符个数

    strstr

    fn strstr(haystack : FFIPtr, needle : FFIPtr) -> FFIPtr

    查找子串

    strtod

    fn strtod(s : FFIPtr, endptr : FFIPtr) -> Double

    strtok

    fn strtok(str : FFIPtr, delim : FFIPtr) -> FFIPtr

    ⚠️ 会修改原字符串,且非线程安全。推荐用 strtok_r/strtok_s。

    strtok_r

    fn strtok_r(str : FFIPtr, delim : FFIPtr, saveptr : FFIPtr) -> FFIPtr

    POSIX 可重入分词(Linux/macOS)

    strtol

    fn strtol(s : FFIPtr, endptr : FFIPtr, base : Int) -> Int64

    struncate

    fn struncate() -> Int

    STRUNCATE (80) — 字符串被截断。

    MSVC Secure CRT 特有。

    unsetenv

    fn unsetenv(name : FFIPtr) -> Int

    删除环境变量。

    返回:
    • 成功:0。
    • 失败:-1。

    write

    fn write(fd : Int, buf : FFIPtr, count : UInt64) -> Int64

    向文件描述符写入。返回写入字节数(-1 = 错误)。