Skip to content

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 中受支持。

FFITypeC 類型別名
cstringchar*
function(void*)(*)()fn, callback
ptrvoid*pointer, void*, char*
i8int8_tint8_t
i16int16_tint16_t
i32int32_tint32_t, int
i64int64_tint64_t
i64_fastint64_t
u8uint8_tuint8_t
u16uint16_tuint16_t
u32uint32_tuint32_t
u64uint64_tuint64_t
u64_fastuint64_t
f32floatfloat
f64doubledouble
boolbool
charchar
napi_envnapi_env
napi_valuenapi_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 編譯器的預處理器定義。

Bun學習網由www.bunjs.com.cn整理維護