公告

FujoOS公布日延期,以仓库发布为准

文档 语言 FFI · 调用别的语言

FFI · 调用别的语言

extern fn 是 0.1.4 Pre2 加进语言的唯一东西。形状很简单——只有签名、末尾一个分号,没有函数体:

loment extern 的形状
extern fn c_add(a: i32, b: i32) -> i32;

fn _start() {
    syscall4(60, c_add(20, 32) as u64, 0, 0);   // 退出码 = C 那边的返回值
}

两条腿,按「对方是什么」分

对方 怎么接 为什么
C / C++ / Rust / Zig / Go / Swift / C# / Fortran extern fn 声明 + loment build --link lib.o 它们导出的是同一种符号与同一套传参约定,所以加一个语言就是加一条构建配方加一条判据
Python / Java / JS / Lua / Ruby 进程桥 loment/lib/proc.lomt(起一个解释器进程,交给它,读回 stdout) 它们不是导出 C ABI 的库,是解释器。代价是多一条进程边界
一个容易误读的区分: 「支持 7 个语言」是保守说法。机制上两条腿各自覆盖一整族——C ABI 那一族是「任何导出 C 符号的东西」,不是七种语言。真正说的是:配方与判据写出来的有七个,其中本机实测跑通五个,余下因为这台机器没装那些工具链而 SKIP。缺的是工具链,不是通路。

这台机器上真跑出来的

语言 走哪条腿 结果
C--link退出码 52
C++--linkextern "C" 包装)退出码 42
Rust--link#[no_mangle] extern "C"退出码 42
Python进程桥(python3 + import json退出码 9
JavaScript进程桥(node + JSON.stringify退出码 7
Java / Zig / Go / Swift / C# / Fortran配方在判据与设计文档里SKIP

一条判据差点没抓住的东西

判据里有一条是证伪:把 C ABI 的前两个寄存器对调,判据必须红。第一版没红——因为 C 夹具只做了 a+ba*b,而这两个运算可交换,寄存器对调之后结果一模一样。换成不可交换的 a-ba*100+b*10+c,对调立刻打红。

这条值得单独写出来:一条不会红的判据不是判据,是装饰。它在第一版里是绿的吗?是。它测到了任何东西吗?没有。

边界(这一版不做的事)

  • 签名只收标量与 ptr —— i8..i64 / u8..u64 / bool / ptrstr 与按值传的聚合类型都在外面,报 E021。宁可不支持,也不静默错编。
  • 不支持变参与回调 —— printf 那类变参函数不支持;把 Loment 函数当函数指针传出去也不支持(lomelf 至今没有间接调用)。
  • 只做静态链接 —— 动态库(.so / .dll)不支持,外部目标文件由使用方自己准备。
  • 进程桥多一条边界 —— 运行期那一族多了进程边界,数据要过 stdout/退出码。它是「能调到」,不是「零成本调到」。
纯 Loment 程序不受影响。 它仍然是 freestanding 的——无运行时、无 libc、不需要 Python。只有声明了 extern 的程序才带外部依赖,而且它自己负责把目标文件准备好。既有程序零改动:extern 是新语法,不用它的程序一个字节都不变(语料 54/54 仍逐字节一致)。
接下来: 设计取舍与分阶段全图见 docs/173,这一版的变更清单见 docs/174;冻结面里 extern fn 的位置见 冻结面;语言本体见 Loment 语言