Files
hakorune/docs/development/roadmap/phases/phase-12/archive/legacy-abi-docs/c-abi.md
Moe Charm 53d88157aa Phase 12: 統一TypeBox ABI実装開始 - ChatGPT5による極小コアABI基盤構築
- TypeBox ABI雛形: メソッドスロット管理システム追加
- Type Registry: Array/Map/StringBoxの基本メソッド定義
- Host API: C ABI逆呼び出しシステム実装
- Phase 12ドキュメント整理: 設計文書統合・アーカイブ化
- MIR Builder: クリーンアップと分離実装完了

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 05:04:56 +09:00

5.5 KiB
Raw Blame History

C ABI プラグインシステム

📦 概要

C ABIは、Nyashの基本プラグインシステムです。C言語の標準的な関数呼び出し規約を使用し、高速かつ軽量な実装を提供します。

🎯 特徴

シンプルさ

  • たった3つの関数で完全なプラグインが作れる
  • 複雑な型システムや継承は不要
  • C言語の知識があれば誰でも書ける

高速性

  • 直接的な関数ポインタ呼び出し
  • オーバーヘッドがほぼゼロ
  • JITコンパイラとの相性も抜群

安定性

  • C ABIは数十年の実績がある標準規格
  • プラットフォーム間での互換性が高い
  • バージョン間の互換性も維持しやすい

📝 基本実装

1. 最小限のプラグイン3つの関数

#include <string.h>
#include <stdlib.h>

// 1. create関数Boxを作成
void* string_create(const char* initial_value) {
    char* str = malloc(strlen(initial_value) + 1);
    strcpy(str, initial_value);
    return str;
}

// 2. method関数メソッドを実行
void* string_method(void* self, const char* method_name, void** args, int arg_count) {
    char* str = (char*)self;
    
    if (strcmp(method_name, "length") == 0) {
        int* result = malloc(sizeof(int));
        *result = strlen(str);
        return result;
    }
    
    if (strcmp(method_name, "toUpperCase") == 0) {
        char* upper = malloc(strlen(str) + 1);
        for (int i = 0; str[i]; i++) {
            upper[i] = toupper(str[i]);
        }
        upper[strlen(str)] = '\0';
        return upper;
    }
    
    return NULL;  // メソッドが見つからない
}

// 3. destroy関数メモリを解放
void string_destroy(void* self) {
    free(self);
}

2. プラグイン設定nyash.toml

[[plugins]]
name = "StringBox"
path = "./string_plugin.so"
type = "c-abi"
version = 1

# メソッドの戻り値型を指定
[plugins.methods]
length = { returns = "integer" }
toUpperCase = { returns = "string" }

🔧 TLVType-Length-Value形式

構造化データのやり取り

C ABIでは、複雑なデータをTLV形式でやり取りします

// TLVヘッダー
typedef struct {
    uint8_t type;     // 1=bool, 2=i64, 3=f64, 5=string, 6=handle
    uint32_t length;  // データ長
    // この後にデータが続く
} TLVHeader;

// 複数の値を返す例
void* math_stats(void* self, const char* method_name, void** args, int arg_count) {
    if (strcmp(method_name, "calculate") == 0) {
        // 3つの値を返す: [min, max, average]
        size_t total_size = sizeof(TLVHeader) * 3 + sizeof(double) * 3;
        uint8_t* buffer = malloc(total_size);
        uint8_t* ptr = buffer;
        
        // min値
        TLVHeader* hdr1 = (TLVHeader*)ptr;
        hdr1->type = 3;  // f64
        hdr1->length = sizeof(double);
        ptr += sizeof(TLVHeader);
        *(double*)ptr = 1.0;
        ptr += sizeof(double);
        
        // 以下同様にmax値、average値を追加...
        
        return buffer;
    }
    return NULL;
}

🚀 TypeBoxC ABIの拡張メカニズム

C ABIの限界を超える

C ABIだけでは、プラグイン間でBoxを生成することができません。例えば、MapBoxがArrayBoxを返したい場合、MapBoxはArrayBoxの実装を知らないため直接作成できません。

この問題を解決するのがTypeBoxです。

TypeBoxとは

TypeBoxは「型情報をBoxとして扱う」という概念です。型の生成方法をBoxとして渡すことで、プラグイン間の連携を可能にします。

// TypeBox構造体型情報をBoxとして扱う
typedef struct {
    uint32_t abi_tag;       // 'TYBX' (0x54594258)
    const char* name;       // "ArrayBox"
    void* (*create)(void);  // Box生成関数
} TypeBox;

// MapBox.keys()の実装 - ArrayBoxのTypeBoxを引数で受け取る
void* map_keys(void* self, void* array_type_box) {
    MapBox* map = (MapBox*)self;
    TypeBox* array_type = (TypeBox*)array_type_box;
    
    // 検証
    if (!array_type || array_type->abi_tag != 0x54594258) {
        return NULL;
    }
    
    // ArrayBoxを生成TypeBox経由
    void* array = array_type->create();
    if (!array) return NULL;
    
    // MapのキーをArrayに追加
    // ArrayBoxのメソッドは別途C API経由で呼ぶ
    
    return array;
}

TypeBoxの利点

  1. プラグイン間の疎結合: 直接的な依存関係なし
  2. 型安全性: abi_tagによる検証
  3. 拡張可能: 新しいBox型の追加が容易
  4. シンプル: 構造体1つ、関数ポインタ1つ

💡 いつC ABIを使うべきか

C ABIが最適な場合

  • シンプルな機能を追加したい
  • 高速性が重要
  • 安定性を重視する
  • 既存のC/C++ライブラリをラップしたい

C ABIでは難しい場合

  • 複雑な継承関係が必要
  • 他言語Python/Go等との相互運用
  • 動的な型変換が頻繁に必要

これらの場合は、C ABI + TypeBoxをベースに構築されたNyash ABIを検討してください。

📊 まとめ

C ABIは「シンプル・高速・安定」の3拍子が揃った、Nyashの基本プラグインシステムです。

  • 最小3関数で実装可能
  • オーバーヘッドがほぼゼロ
  • TypeBoxによる拡張で、プラグイン間連携も可能

迷ったらC ABIから始めるのが正解です!