# 機能設計書 65-bun:ffi

## 概要

本ドキュメントは、Bunランタイムのネイティブ関数呼び出し機能（`bun:ffi`モジュール）の設計仕様を記載する。

### 本機能の処理概要

`bun:ffi`は、C言語やその他のネイティブライブラリの関数をJavaScriptから直接呼び出すための機能（Foreign Function Interface）を提供する。動的リンクライブラリ（.so, .dylib, .dll）のロード、関数のシンボル解決、型変換を自動的に行う。

**業務上の目的・背景**：Node.jsのN-APIや従来のFFIモジュールは設定が複雑で、性能オーバーヘッドがあった。Bunのネイティブ統合により、シンプルなAPIで高性能なネイティブライブラリ連携を実現する。

**機能の利用シーン**：
- システムAPIの直接呼び出し
- 既存のCライブラリの活用
- 高性能な数値計算ライブラリの利用
- ハードウェアアクセス
- レガシーシステムとの連携

**主要な処理内容**：
1. 動的ライブラリのロード（dlopen）
2. 関数シンボルの解決
3. JavaScriptからネイティブ関数の呼び出し
4. 引数の型変換（JavaScript → C）
5. 戻り値の型変換（C → JavaScript）
6. コールバック関数の登録（JSCallback）

**関連システム・外部連携**：システムの動的リンクライブラリ、カスタムCライブラリ

**権限による制御**：ファイルシステムアクセス権限、ライブラリロード権限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はAPI専用であり、直接関連する画面はない |

## 機能種別

システム連携 / ネイティブ連携 / 低レベルAPI

## 入力仕様

### 入力パラメータ

#### dlopen

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes | ライブラリパス | ファイル存在確認 |
| symbols | object | Yes | 関数定義オブジェクト | - |

#### symbols定義

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| args | FFIType[] | No | 引数の型リスト | 有効なFFIType |
| returns | FFIType | No | 戻り値の型 | 有効なFFIType |

#### FFIType一覧

| 型名 | 説明 |
|------|------|
| char, i8, int8_t | 8ビット符号付き整数 |
| u8, uint8_t | 8ビット符号なし整数 |
| i16, int16_t | 16ビット符号付き整数 |
| u16, uint16_t | 16ビット符号なし整数 |
| i32, int32_t, int, c_int | 32ビット符号付き整数 |
| u32, uint32_t, c_uint | 32ビット符号なし整数 |
| i64, int64_t | 64ビット符号付き整数 |
| u64, uint64_t | 64ビット符号なし整数 |
| f32, float | 32ビット浮動小数点 |
| f64, double | 64ビット浮動小数点 |
| bool | ブーリアン |
| ptr, pointer, void* | ポインタ |
| cstring, char* | Cスタイル文字列 |
| void | 戻り値なし |
| function, callback, fn | 関数ポインタ |
| buffer | TypedArray |

### 入力データソース

- 動的リンクライブラリファイル（.so, .dylib, .dll）
- シンボル定義オブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Library | object | ロードしたライブラリオブジェクト |
| symbols | object | 呼び出し可能な関数群 |
| close | function | ライブラリを閉じる関数 |

### 出力先

- JavaScript関数オブジェクト（ネイティブ関数ラッパー）

## 処理フロー

### 処理シーケンス

```
1. ライブラリロード
   └─ dlopen()でライブラリをメモリにロード
2. シンボル解決
   └─ dlsym()で関数アドレスを取得
3. ラッパー関数生成
   └─ 型変換コードを動的生成
4. 関数呼び出し
   └─ JavaScript値をC型に変換して呼び出し
5. 戻り値処理
   └─ C戻り値をJavaScript値に変換
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[dlopen]
    B --> C{ロード成功?}
    C -->|No| D[エラーを返却]
    C -->|Yes| E[シンボル定義を解析]
    E --> F[各シンボルでdlsym]
    F --> G{シンボル解決成功?}
    G -->|No| D
    G -->|Yes| H[FFIBuilder でラッパー生成]
    H --> I[ライブラリオブジェクト返却]
    I --> J{関数呼び出し}
    J --> K[引数を型変換]
    K --> L[ネイティブ関数実行]
    L --> M[戻り値を型変換]
    M --> N[結果返却]
    N --> O[終了]
    D --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 型変換 | JavaScript値を対応するC型に自動変換 | 関数呼び出し時 |
| BR-002 | BigInt対応 | i64/u64はBigIntまたはNumber（安全範囲内）を受け付け | 64ビット整数型 |
| BR-003 | ポインタ変換 | number、TypedArray、ArrayBufferをポインタに変換 | ptr型 |
| BR-004 | CString変換 | 戻り値のcstringはCStringオブジェクトとして返却 | cstring戻り値 |

### 計算ロジック

- i64_fast/u64_fast: Number.MAX_SAFE_INTEGER範囲内ならNumberで返却、超過時はBigInt
- uint32_t: 負数は0、オーバーフローは0xFFFFFFFFでクランプ

## データベース操作仕様

本機能はデータベース操作に関係しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeError | 型エラー | 不正な型のパラメータ | 正しい型を渡す |
| Error | ロードエラー | ライブラリが見つからない | パスを確認 |
| Error | シンボルエラー | 関数が見つからない | シンボル名を確認 |

### リトライ仕様

特になし。エラー時は即座に例外をスロー。

## トランザクション仕様

本機能にトランザクション概念は適用外。

## パフォーマンス要件

- 関数呼び出しごとの動的コード生成ではなく、事前にラッパーを生成
- 引数数に応じた最適化されたラッパー（0〜8引数まで特殊化）
- BigIntとNumber間の変換を最適化（安全範囲内ならNumber使用）

## セキュリティ考慮事項

- ネイティブコード実行のため、信頼できるライブラリのみを使用
- 不正なポインタ操作によるメモリ破損の可能性
- JITコンパイル保護の一時的な無効化（ARM Mac）

## 備考

- プラットフォーム依存: .so（Linux）、.dylib（macOS）、.dll（Windows）
- TCC（Tiny C Compiler）との統合でランタイムCコンパイルも可能
- JSCallbackでJavaScript関数をCコールバックとして渡せる

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、FFITypeとffiWrappersの型マッピングを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ffi.ts | `src/js/bun/ffi.ts` | FFIType定義（1-61行目） |

**読解のコツ**: FFITypeのキー・値マッピングで、文字列型名と数値型IDの対応を把握する。

#### Step 2: 型変換ラッパーを理解する

各型に対する変換ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ffi.ts | `src/js/bun/ffi.ts` | ffiWrappers配列（159-338行目） |

**主要処理フロー**:
1. **159-184行目**: 整数型のクランプ処理
2. **185-242行目**: i64/u64のBigInt変換
3. **258-277行目**: float/double/bool変換
4. **293-338行目**: pointer/cstring/buffer/function変換

#### Step 3: ラッパー関数生成を理解する

FFIBuilderによる動的関数生成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ffi.ts | `src/js/bun/ffi.ts` | FFIBuilder（340-400行目〜） |

**主要処理フロー**:
- **340-368行目**: 動的関数コード生成
- **373-399行目**: 引数数に応じたラッパー特殊化

#### Step 4: JSCallbackを理解する

JavaScriptコールバックのネイティブ化を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ffi.ts | `src/js/bun/ffi.ts` | JSCallbackクラス（82-116行目） |

**主要処理フロー**:
- **82-116行目**: JSCallbackクラス定義
- ptr プロパティでCポインタを取得
- close()でコールバックを解放

### プログラム呼び出し階層図

```
bun:ffi API
    │
    ├─ dlopen (ffi.ts)
    │      ├─ nativeDLOpen (Zig)
    │      └─ FFIBuilder (動的ラッパー生成)
    │
    ├─ ptr / toBuffer / toArrayBuffer
    │      └─ ffi.ptr (Zig)
    │
    ├─ CString (ffi.ts)
    │      └─ BunCString (Zig)
    │
    └─ JSCallback (ffi.ts)
           └─ nativeCallback (Zig)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

ライブラリパス ──────────▶ dlopen() ──────────────────▶ Library Object
                                │
シンボル定義 ────────────▶ dlsym() ───────────────────▶ 関数アドレス
                                │
                                ▼
                         FFIBuilder() ────────────────▶ ラッパー関数
                                │
JavaScript引数 ──────────▶ ffiWrappers[型]変換 ────────▶ C型引数
                                │
                                ▼
                         ネイティブ関数呼び出し
                                │
C戻り値 ─────────────────▶ 戻り値変換 ────────────────▶ JavaScript値
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ffi.ts | `src/js/bun/ffi.ts` | ソース | TypeScript FFI API |
| ffi.zig | `src/bun.js/api/ffi.zig` | ソース | Zig FFI実装 |
| ffi.classes.ts | `src/bun.js/api/ffi.classes.ts` | ソース | JSバインディング定義 |
