> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C 编译器

> 使用低开销从 JavaScript 编译和运行 C 代码

`bun:ffi` 具有从 JavaScript 以低开销编译和运行 C 代码的实验性支持。

***

## 使用方法（`bun:ffi` 中的 cc）

更多信息请参阅[介绍博客文章](https://bun.com/blog/compile-and-run-c-in-js)。

JavaScript 代码：

```ts hello.ts icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}}
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("宇宙的答案是什么？", hello());
```

C 源代码：

```c hello.c theme={"theme":{"light":"github-light","dark":"dracula"}}
int hello() {
  return 42;
}
```

运行 `hello.js` 时，将打印：

```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun hello.js
宇宙的答案是什么？ 42
```

底层，`cc` 使用 [TinyCC](https://bellard.org/tcc/) 来编译 C 代码，然后与 JavaScript 运行时链接，高效地进行类型原地转换。

### 基本类型

`cc` 支持 [`dlopen`](/runtime/ffi) 中相同的 `FFIType` 值。

| `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`   |                           |

### 字符串、对象及非基本类型

为方便操作字符串、对象以及其他无法 1:1 映射到 C 类型的非基本类型，`cc` 支持 N-API。

如果想在 C 函数中传递或接收 JavaScript 值且不进行任何类型转换，可以使用 `napi_value`。

你也可以传递一个 `napi_env`，用以接收调用 JavaScript 函数时使用的 N-API 环境。

#### 从 C 返回字符串到 JavaScript

例如，如果 C 中有一个字符串，可以这样返回给 JavaScript：

```ts hello.ts theme={"theme":{"light":"github-light","dark":"dracula"}}
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 hello.c theme={"theme":{"light":"github-light","dark":"dracula"}}
#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 hello.c theme={"theme":{"light":"github-light","dark":"dracula"}}
#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 theme={"theme":{"light":"github-light","dark":"dracula"}}
type Library = string[];

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

#### `symbols`

使用 `symbols` 对象来指定要暴露给 JavaScript 的函数和变量。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
type Symbols = {
  [key: string]: {
    args: FFIType[];
    returns: FFIType;
  };
};
```

#### `source`

`source` 是要编译并与 JavaScript 运行时链接的 C 代码文件路径。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
type Source = string | URL | BunFile;

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

#### `flags: string | string[]`

`flags` 是一个可选的字符串数组，传递给 TinyCC 编译器。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
type Flags = string | string[];
```

这些是类似 `-I` 指定包含目录和 `-D` 预处理定义的标志。

#### `define: Record<string, string>`

`define` 是一个可选对象，传递给 TinyCC 编译器。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
type Defines = Record<string, string>;

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

这些是传递给 TinyCC 编译器的预处理定义。
