bun:ffi 具有實驗性支持,用於以低開銷從 JavaScript 編譯和運行 C 代碼。
用法(bun:ffi 中的 cc)
有關更多信息,請參閱 介紹性博客文章。
JavaScript:
ts
import { cc } from "bun:ffi";
import source from "./hello.c" with { type: "file" };
const {
symbols: { hello },
} = cc({
source,
symbols: {
hello: {
args: [],
returns: "int",
},
},
});
console.log("What is the answer to the universe?", hello());C 源代碼:
c
int hello() {
return 42;
}當你運行 hello.js 時,它將打印:
sh
bun hello.js
What is the answer to the universe? 42在底層,cc 使用 TinyCC 編譯 C 代碼,然後將其與 JavaScript 運行時鏈接,高效地就地轉換類型。
原始類型
dlopen 中相同的 FFIType 值在 cc 中受支持。
FFIType | C 類型 | 別名 |
|---|---|---|
| cstring | char* | |
| function | (void*)(*)() | fn, callback |
| ptr | void* | pointer, void*, char* |
| i8 | int8_t | int8_t |
| i16 | int16_t | int16_t |
| i32 | int32_t | int32_t, int |
| i64 | int64_t | int64_t |
| i64_fast | int64_t | |
| u8 | uint8_t | uint8_t |
| u16 | uint16_t | uint16_t |
| u32 | uint32_t | uint32_t |
| u64 | uint64_t | uint64_t |
| u64_fast | uint64_t | |
| f32 | float | float |
| f64 | double | double |
| bool | bool | |
| char | char | |
| napi_env | napi_env | |
| napi_value | napi_value |
字符串、對象和非原始類型
為了更容易處理字符串、對象和其他不與 C 類型 1:1 映射的其他非原始類型,cc 支持 N-API。
要從 C 函數傳遞或接收 JavaScript 值而無需任何類型轉換,你可以使用 napi_value。
你還可以傳遞 napi_env 來接收用於調用 JavaScript 函數的 N-API 環境。
將 C 字符串返回到 JavaScript
例如,如果你在 C 中有一個字符串,可以像這樣將其返回到 JavaScript:
ts
import { cc } from "bun:ffi";
import source from "./hello.c" with { type: "file" };
const {
symbols: { hello },
} = cc({
source,
symbols: {
hello: {
args: ["napi_env"],
returns: "napi_value",
},
},
});
const result = hello();在 C 中:
c
#include <node/node_api.h>
napi_value hello(napi_env env) {
napi_value result;
napi_create_string_utf8(env, "Hello, Napi!", NAPI_AUTO_LENGTH, &result);
return result;
}你也可以使用它來返回其他類型,如對象和數組:
c
#include <node/node_api.h>
napi_value hello(napi_env env) {
napi_value result;
napi_create_object(env, &result);
return result;
}cc 參考
library: string[]
library 數組用於指定應與 C 代碼鏈接的庫。
ts
type Library = string[];
cc({
source: "hello.c",
library: ["sqlite3"],
});symbols
symbols 對象用於指定應暴露給 JavaScript 的函數和變量。
ts
type Symbols = {
[key: string]: {
args: FFIType[];
returns: FFIType;
};
};source
source 是要編譯並與 JavaScript 運行時鏈接的 C 代碼的文件路徑。
ts
type Source = string | URL | BunFile;
cc({
source: "hello.c",
symbols: {
hello: {
args: [],
returns: "int",
},
},
});flags: string | string[]
flags 是應傳遞給 TinyCC 編譯器的可選字符串數組。
ts
type Flags = string | string[];這些是像 -I 用於包含目錄和 -D 用於預處理器定義的標志。
define: Record<string, string>
define 是應傳遞給 TinyCC 編譯器的可選對象。
ts
type Defines = Record<string, string>;
cc({
source: "hello.c",
define: {
NDEBUG: "1",
},
});這些是傳遞給 TinyCC 編譯器的預處理器定義。