bun:ffi
實驗性地支援從 JavaScript 編譯和執行 C 語言,且具有低開銷。
用法 (bun:ffi
中的 cc)
請參閱介紹部落格文章以取得更多資訊。
JavaScript
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 原始碼
int hello() {
return 42;
}
當您執行 hello.js
時,它會印出
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。
若要傳遞或接收 JavaScript 值,而無需從 C 函數進行任何類型轉換,您可以使用 napi_value
。
您也可以傳遞 napi_env
以接收用於呼叫 JavaScript 函數的 N-API 環境。
將 C 字串傳回 JavaScript
例如,如果您在 C 語言中有一個字串,您可以像這樣將其傳回 JavaScript
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 語言中
#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;
}
您也可以使用此方法傳回其他類型,例如物件和陣列
#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 程式碼連結的函式庫。
type Library = string[];
cc({
source: "hello.c",
library: ["sqlite3"],
});
symbols
symbols
物件用於指定應公開給 JavaScript 的函數和變數。
type Symbols = {
[key: string]: {
args: FFIType[];
returns: FFIType;
};
};
source
source
是 C 程式碼的檔案路徑,該程式碼應編譯並與 JavaScript 執行時環境連結。
type Source = string | URL | BunFile;
cc({
source: "hello.c",
symbols: {
hello: {
args: [],
returns: "int",
},
},
});
flags: string | string[]
flags
是一個可選的字串陣列,應傳遞給 TinyCC 編譯器。
type Flags = string | string[];
這些是諸如 -I
(用於包含目錄)和 -D
(用於前處理器定義)之類的標誌。
define: Record<string, string>
define
是一個可選的物件,應傳遞給 TinyCC 編譯器。
type Defines = Record<string, string>;
cc({
source: "hello.c",
define: {
"NDEBUG": "1",
},
});
這些是傳遞給 TinyCC 編譯器的前處理器定義。