Skip to content

bun:ffi prend en charge de manière expérimentale la compilation et l'exécution de code C depuis JavaScript avec une faible surcharge.


Utilisation (cc dans bun:ffi) ​

Consultez l'article de blog d'introduction pour plus d'informations.

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("Quelle est la réponse à l'univers ?", hello());

Source C :

c
int hello() {
  return 42;
}

Lorsque vous exécutez hello.js, cela affichera :

sh
bun hello.js
Quelle est la réponse à l'univers ? 42

Sous le capot, cc utilise TinyCC pour compiler le code C puis le lier avec le runtime JavaScript, en convertissant efficacement les types sur place.

Types primitifs ​

Les mêmes valeurs FFIType que dans dlopen sont prises en charge dans cc.

FFITypeType CAlias
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

Chaînes, objets et types non primitifs ​

Pour faciliter le travail avec les chaînes, les objets et autres types non primitifs qui ne correspondent pas 1:1 aux types C, cc prend en charge N-API.

Pour passer ou recevoir des valeurs JavaScript sans conversions de type depuis une fonction C, vous pouvez utiliser napi_value.

Vous pouvez également passer un napi_env pour recevoir l'environnement N-API utilisé pour appeler la fonction JavaScript.

Retourner une chaîne C vers JavaScript ​

Par exemple, si vous avez une chaîne en C, vous pouvez la retourner vers JavaScript comme ceci :

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();

Et en 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;
}

Vous pouvez également utiliser cela pour retourner d'autres types comme des objets et des tableaux :

c
#include <node/node_api.h>

napi_value hello(napi_env env) {
  napi_value result;
  napi_create_object(env, &result);
  return result;
}

Référence cc ​

library: string[] ​

Le tableau library est utilisé pour spécifier les bibliothèques qui doivent être liées avec le code C.

ts
type Library = string[];

cc({
  source: "hello.c",
  library: ["sqlite3"],
});

symbols ​

L'objet symbols est utilisé pour spécifier les fonctions et variables qui doivent être exposées à JavaScript.

ts
type Symbols = {
  [key: string]: {
    args: FFIType[];
    returns: FFIType;
  };
};

source ​

Le source est un chemin de fichier vers le code C qui doit être compilé et lié avec le runtime JavaScript.

ts
type Source = string | URL | BunFile;

cc({
  source: "hello.c",
  symbols: {
    hello: {
      args: [],
      returns: "int",
    },
  },
});

flags: string | string[] ​

Le flags est un tableau optionnel de chaînes qui doit être passé au compilateur TinyCC.

ts
type Flags = string | string[];

Ce sont des indicateurs comme -I pour les répertoires d'inclusion et -D pour les définitions de préprocesseur.

define: Record<string, string> ​

Le define est un objet optionnel qui doit être passé au compilateur TinyCC.

ts
type Defines = Record<string, string>;

cc({
  source: "hello.c",
  define: {
    NDEBUG: "1",
  },
});

Ce sont des définitions de préprocesseur passées au compilateur TinyCC.

Bun édité par www.bunjs.com.cn