Skip to main content
版本: 0.10

WASM API

KCL 核心用 Rust 编写,可以使用 cargo 等工具链编译到 wasm-wasi 目标。在 WASM 的帮助下,也可以轻松实现多语言和浏览器集成。以下是在浏览器, Node.js 环境, Go 和 Rust 中使用 KCL WASM 模块的方法。

快速开始

可以从这里找到 KCL WASM 模块。

浏览器环境

安装依赖

npm install buffer @wasmer/wasi @kcl-lang/wasm-lib

注意:buffer 是 @wasmer/wasi 所需的依赖。

编写代码

import { load, invokeKCLRun } from "@kcl-lang/wasm-lib";

async function main() {
const inst = await load();
const result = invokeKCLRun(inst, {
filename: "test.k",
source: `
schema Person:
name: str
p = Person {name = "Alice"}`,
});
console.log(result);
}

main();

在这里,我们使用 webpack 来打包网站, webpack.config.js 的配置如下。

注意:此配置包含了 @wasmer/wasi 所需的必要设置和其他必需的插件。

const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require("path");
const webpack = require("webpack");

const dist = path.resolve("./dist");
const isProduction = process.argv.some((x) => x === "--mode=production");
const hash = isProduction ? ".[contenthash]" : "";

module.exports = {
mode: "development",
entry: {
main: "./src/main.ts",
},
target: "web",
output: {
path: dist,
filename: `[name]${hash}.js`,
clean: true,
},
devServer: {
hot: true,
port: 9000,
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.m?js$/,
resourceQuery: { not: [/(raw|wasm)/] },
},
{
resourceQuery: /raw/,
type: "asset/source",
},
{
resourceQuery: /wasm/,
type: "asset/resource",
generator: {
filename: "wasm/[name][ext]",
},
},
],
},
plugins: [
new MiniCssExtractPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./src/index.html"),
}),
new webpack.IgnorePlugin({
resourceRegExp: /^(path|ws|crypto|fs|os|util|node-fetch)$/,
}),
// needed by @wasmer/wasi
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
}),
],
externals: {
// needed by @wasmer/wasi
"wasmer_wasi_js_bg.wasm": true,
},
resolve: {
fallback: {
// needed by @wasmer/wasi
buffer: require.resolve("buffer/"),
},
},
};

完整的代码示例可以在这里找到。

错误排查

如果遇到任何问题,请确保:

  • 所有依赖都正确安装。
  • webpack.config.js 配置正确。
  • 使用的是支持 WebAssembly 的现代浏览器。
  • KCL WASM 模块正确加载并可访问。

Node.js

安装依赖:

npm install @kcl-lang/wasm-lib

编写代码:

import { load, invokeKCLRun } from "@kcl-lang/wasm-lib";

async function main() {
const inst = await load();
const result = invokeKCLRun(inst, {
filename: "test.k",
source: `
schema Person:
name: str

p = Person {name = "Alice"}`,
});
console.log(result);
}

main();

输出结果为:

p:
name: Alice

完整的代码示例可以在这里找到。

Rust

在 Rust 中,我们以 wasmtime 为例,当然你也可以使用其他支持 WASI 的运行时来完成这一任务。

安装依赖:

cargo add kcl-wasm-lib --git https://github.com/kcl-lang/lib
cargo add anyhow

编写代码:

use anyhow::Result;
use kcl_wasm_lib::{KCLModule, RunOptions};

fn main() -> Result<()> {
let opts = RunOptions {
filename: "test.k".to_string(),
source: "a = 1".to_string(),
};
// 注意修改路径为你的 kcl.wasm 路径
let mut module = KCLModule::from_path("path/to/kcl.wasm")?;
let result = module.run(&opts)?;
println!("{}", result);
Ok(())
}

输出结果为:

a: 1

完整的代码示例可以在这里找到。

Go

在 Go 中,我们以 wasmtime 为例,当然你也可以使用其他支持 WASI 的运行时来完成这一任务。

编写代码,关于包 github.com/kcl-lang/wasm-lib/pkg/module 的代码可以在这里找到。

package main

import (
"fmt"

"github.com/kcl-lang/wasm-lib/pkg/module"
)

func main() {
m, err := module.New("path/to/kcl.wasm")
if err != nil {
panic(err)
}
result, err := m.Run(&module.RunOptions{
Filename: "test.k",
Source: "a = 1",
})
if err != nil {
panic(err)
}
fmt.Println(result)
}

输出结果为:

a: 1

完整的代码示例可以在这里找到。