外部函数接口 (FFI)
你可以在月兔中通过外部函数接口来使用外部的函数,与宿主环境交互。一般在嵌入浏览器环境或命令行环境(通过Wasmtime等项目)时使用。
⚠ 警告:月兔还在初期开发阶段,内容可能会过时。
外部函数接口
声明外部引用
你可以定义一个这样的外部引用类型:
type Canvas_ctx
这将会定义一个外部对象的引用。在我们的例子中,它代表了宿主 JavaScript 环境中的一个CanvasRenderingContext2D
对象。
声明外部函数
你可以像这样定义一个外部函数:
fn cos(d : Double) -> Double = "Math" "cos"
它和正常的函数定义十分相像,除了函数体被替换为两个字符串。
对于 WasmGC 后端,这两个字符串是用来在 Wasm 导入的对象中识别特定的函数:第一个字符串是模 块名称,第二个字符串是函数名称。对于 JS 后端,这两个字符串被用于访问全局命名空间中的一个静态函数。上述例子会编译为类似const cos = (d) => Math.cos(d)
你也可以定义内联函数,函数体是一个字符串。
对于 WasmGC 后端,你可以以一个不含名称的 Wasm 函数定义它(名称将会在之后自动生成):
extern "wasm" fn abs(d : Double) -> Double =
#|(func (param f64) (result f64))
而对于 JS 后端,你可以定义一个箭头函数表达式:
extern "js" fn abs(d : Double) -> Double =
#|(d) => Math.abs(d)
在声明之后,你可以像普通的函数那样使用外部函数。
对于多后端项目,你可以在以.wasm.mbt
.wasm-gc.mbt
.js.mbt
结尾的文件中定义后端相关代码。
你也可以定义一个使用外部引用类型的外部函数,就像这样:
fn begin_path(self: Canvas_ctx) = "canvas" "begin_path"
之后可以将它应用到拥有的外部对象的引用上,如:context.begin_path()
。
导出函数
公开函数(非方法、非多态)可以被导出,需要在对应包的moon.pkg.json
中添加链接设置:
{
"link": {
"wasm": {
"exports": [
"add",
"fib:test"
]
},
"wasm-gc": {
"exports": [
"add",
"fib:test"
]
},
"js": {
"exports": [
"add",
"fib:test"
],
"format": "esm"
}
}
}
每一个后端都有一个单独的定义。对 JS 后端,还有一个额外的format
选项,可以用来指定生成的 JS 文件,是 ES Module(esm
),还是 CommonJS module (cjs
),还是立即调用函数表达式(iife
)。
上面的例子中,add
和fib
函数将会在编译时被导出,并且fib
函数将被以test
为名导出。
对于 WasmGC 后端,_start
函数总是应当被使用,以初始化月兔程序中定义的全局实例。