# 機能設計書 66-ccall

## 概要

本ドキュメントは、Juliaにおける C 関数の直接呼び出し機構（`@ccall` / `ccall` / `@cfunction`）の設計と実装を記述するものである。

### 本機能の処理概要

本機能は、Julia から C 言語の関数を直接呼び出すための Foreign Function Interface (FFI) を提供する。`ccall` / `@ccall` による C 関数の呼び出しと、`@cfunction` による Julia 関数の C コールバック登録を実現する。

**業務上の目的・背景**：Julia は科学計算・数値計算分野を主要ターゲットとしており、既存の C/Fortran ライブラリ（BLAS, LAPACK, GMP, MPFR など）を直接呼び出す能力が不可欠である。ccall は FFI のオーバーヘッドを最小限に抑え、ネイティブ C コードに近い性能で外部ライブラリを利用可能にする。

**機能の利用シーン**：BLAS/LAPACK の線形代数ルーチン呼び出し、OS のシステムコール（libc 関数）呼び出し、GPU ライブラリ（CUDA など）との連携、libcurl による HTTP 通信、外部 C ライブラリのラッピングに利用される。

**主要な処理内容**：
1. `ccall((:func, "lib"), RetType, (ArgTypes...), args...)` による C 関数呼び出し
2. `@ccall lib.func(arg::Type, ...)::RetType` マクロによる簡潔な構文
3. `@cfunction(f, RetType, (ArgTypes...))` による Julia 関数の C コールバック化
4. 引数の自動型変換（`cconvert` / `unsafe_convert`）
5. GC セーフティ制御（`disable_sigint` / `reenable_sigint`）
6. `@ccallable` による C から呼び出し可能な Julia 関数の公開

**関連システム・外部連携**：LLVM コード生成（`src/ccall.cpp`）、動的ライブラリローダー（`src/dlload.c`）、GC との連携。

**権限による制御**：なし（ただし、unsafe 操作であるためセグフォルトのリスクがある）。

## 関連画面

該当なし。本機能はプログラマティックに使用されるAPI。

## 機能種別

外部連携（FFI）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| func | `Symbol` or `Expr` | Yes | C 関数名（または (シンボル, ライブラリ) タプル） | - |
| RetType | `Type` | Yes | C 関数の戻り値型 | 有効な C 互換型 |
| ArgTypes | `Tuple{Type...}` | Yes | C 関数の引数型タプル | 有効な C 互換型 |
| args | 可変長 | Yes | 実際の引数値 | ArgTypes と整合すること |
| gc_safe | `Bool` | No | GC セーフモードで呼び出すか（@ccall） | `true` or `false` |

### 入力データソース

ユーザーコードからの直接呼び出し、外部共有ライブラリのシンボル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | RetType | C 関数の戻り値（自動型変換済み） |
| cfunction_ptr | `Ptr{Cvoid}` or `CFunction` | @cfunction の場合の関数ポインタ |

### 出力先

呼び出し元に値として返却

## 処理フロー

### 処理シーケンス

```
1. @ccall マクロ展開
   └─ ccall_macro_parse で式を解析し ccall 式に変換
2. 引数の型変換
   └─ 各引数に対して cconvert → unsafe_convert を適用
3. ライブラリ/シンボルの解決
   └─ 動的ライブラリからシンボルアドレスを取得
4. C 関数呼び出し
   └─ LLVM レベルで直接 C 呼び出し規約に従い関数呼び出し
5. 戻り値の変換
   └─ C の戻り値を Julia の型に変換
6. GC ルートの管理
   └─ GC.@preserve で引数のGC保護を保証
```

### フローチャート

```mermaid
flowchart TD
    A["@ccall lib.func(args...)::RetType"] --> B[ccall_macro_parse]
    B --> C[式の解析: func, rettype, argtypes, args]
    C --> D[cconvert で引数変換]
    D --> E[unsafe_convert でポインタ変換]
    E --> F[ccall intrinsic 呼び出し]
    F --> G[LLVM C ABI に従った関数呼び出し]
    G --> H[戻り値の Julia 型への変換]
    H --> I[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-01 | 型アノテーション必須 | @ccall のすべての引数に型アノテーションが必要 | @ccall 使用時 |
| BR-66-02 | リテラルタプル | @cfunction の引数型はリテラルタプルでなければならない | @cfunction 使用時 |
| BR-66-03 | GC 保護 | ccall 中は引数のGC回収を防ぐために適切な保護が必要 | ccall 使用時 |
| BR-66-04 | sigatomic | 外部 C コードの実行中は Ctrl-C が遅延される | disable_sigint 使用時 |
| BR-66-05 | varargs 対応 | 可変長引数の C 関数は `;` で固定/可変部分を区切る | @ccall で varargs 使用時 |

### 計算ロジック

該当なし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | @ccall の引数に型アノテーションがない場合 | 型アノテーションを追加 |
| - | ArgumentError | @ccall で戻り値型が指定されていない場合 | 戻り値型を追加 |
| - | UVError | ライブラリのロードに失敗した場合 | ライブラリパスを確認 |
| - | セグメンテーション違反 | 不正なポインタアクセスや型の不一致 | 引数の型と値を確認 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ccall のオーバーヘッドは最小限（ネイティブ C 呼び出しに近い性能）
- 引数の型変換は可能な限りコンパイル時に解決される

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

- ccall は unsafe 操作であり、不正な引数によりセグメンテーション違反やメモリ破壊を引き起こす可能性がある
- `@cfunction` で登録したコールバックは C 側から任意のタイミングで呼び出される可能性がある

## 備考

- `ccall` は Julia のコンパイラ組み込み機能（intrinsic）として実装されている
- `@ccall` は Julia 1.5 以降で利用可能な構文糖衣
- `gc_safe=true` オプション（@ccall）により、長時間実行の C 関数呼び出し中に他のスレッドが GC を実行可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | c.jl | `base/c.jl` | `CFunction` 構造体（29-35行目）: @cfunction の返り値型。ptr, f, _1, _2 フィールドを保持するGCハンドル |

**読解のコツ**: `ccall` 自体はコンパイラ intrinsic であり、Julia コードとしての定義はない。`@ccall` マクロが `ccall` 式に展開される。

#### Step 2: @cfunction マクロを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | c.jl | `base/c.jl` | `@cfunction` マクロ（39-79行目）: Julia 関数を C コールバックに変換 |

**主要処理フロー**:
1. **65-67行目**: 引数型がリテラルタプルであることを検証
2. **68-69行目**: タプルを svec 呼び出しに変換
3. **70-76行目**: `$` 接頭辞の有無で動的/静的 cfunction を分岐
4. **77行目**: `:cfunction` Expr ノードを生成

#### Step 3: @ccall マクロを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | c.jl | `base/c.jl` | `ccall_macro_parse` 関数（277-349行目）: @ccall 式の構文解析 |
| 3-2 | c.jl | `base/c.jl` | `ccall_macro_lower` 関数: ccall 式への lowering |

**主要処理フロー**:
- **303-306行目**: 戻り値型の抽出
- **314-328行目**: 関数名の解析（`.` ノード、`$` 補間、シンボル）
- **330-337行目**: varargs の検出
- **340-349行目**: 引数と型の収集（型アノテーション必須）

#### Step 4: シグナル制御を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | c.jl | `base/c.jl` | `disable_sigint` / `reenable_sigint` 関数（148-185行目）: Ctrl-C 制御 |
| 4-2 | c.jl | `base/c.jl` | `sigatomic_begin` / `sigatomic_end`（145-146行目）: 低レベルシグナル制御 |

#### Step 5: @ccallable を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | c.jl | `base/c.jl` | `@ccallable` マクロと `expand_ccallable` 関数（210-262行目）: C から呼び出し可能な Julia 関数の公開 |

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

```
@ccall lib.func(args...)::RetType
    │
    ├─ ccall_macro_parse()        # 式の解析
    │      └─ 関数名/型/引数の抽出
    │
    ├─ ccall_macro_lower()        # ccall 式へ変換
    │      ├─ cconvert()          # Julia → C 変換準備
    │      └─ unsafe_convert()    # 実際のポインタ変換
    │
    └─ ccall intrinsic            # コンパイラ組み込み
           └─ src/ccall.cpp       # LLVM IR 生成

@cfunction(f, RetType, (ArgTypes...))
    └─ :cfunction Expr → コンパイラ処理

@ccallable function f(...)::RetType ... end
    ├─ expand_ccallable()         # マクロ展開
    └─ _ccallable()               # C API 登録
           └─ jl_extern_c()      # ランタイム登録
```

### データフロー図

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

Julia 引数値 ──────▶ cconvert() ──▶ unsafe_convert()
                         │                │
C 関数シンボル ────▶    │                ▼
ライブラリ名 ─────▶ dlsym() ──▶ 関数アドレス
                         │                │
                         ▼                ▼
                    ccall intrinsic ──▶ C ABI 呼び出し
                         │
                         ▼
                    戻り値変換 ──▶ Julia 値
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| c.jl | `base/c.jl` | ソース | ccall 関連の Julia レベル定義 |
| ccall.cpp | `src/ccall.cpp` | ソース（C++） | ccall の LLVM コード生成 |
| dlload.c | `src/dlload.c` | ソース（C） | 動的ライブラリのロードとシンボル解決 |
| ctypes.jl | `base/ctypes.jl` | ソース | C 互換型定義（No.69） |
| pointer.jl | `base/pointer.jl` | ソース | ポインタ操作（No.67） |
| refpointer.jl | `base/refpointer.jl` | ソース | Ref 型の定義 |
