プラグイン開発ガイド
はじむでは、C言語(または共有ライブラリを生成できる任意の言語)でネイティブプラグインを開発できます。
統一拡張子 .hjp(Hajimu Plugin)により、Windows・macOS・Linux で共通のファイルが使えます。
概要
はじむのプラグインシステムは2種類の拡張方法を提供します。
C拡張プラグイン (.hjp)
C/C++/Rust/Go 等で高速なネイティブライブラリを開発。数学関数、暗号処理、画像処理など計算量が多い処理に最適。
はじむパッケージ (.jp)
はじむ言語自体で書かれたライブラリ。ユーティリティ、データ処理、ビジネスロジックなど汎用的な用途に。
クイックスタート:最初のプラグイン
3ステップでプラグインを作成・使用できます。
ステップ 1:プラグインを書く
hello_plugin.c を作成します。
#include "hajimu_plugin.h"
// プラグイン関数: 挨拶を表示
static Value fn_hello(int argc, Value *argv) {
(void)argc;
if (argv[0].type == VALUE_STRING) {
printf("こんにちは、%sさん!\n", argv[0].string.data);
}
return hajimu_null();
}
// 関数テーブル
static HajimuPluginFunc functions[] = {
{"挨拶", fn_hello, 1, 1},
};
// 初期化関数(必須)
HAJIMU_PLUGIN_EXPORT HajimuPluginInfo *hajimu_plugin_init(void) {
static HajimuPluginInfo info = {
.name = "hello_plugin",
.version = "1.0.0",
.author = "あなたの名前",
.description = "挨拶プラグイン",
.functions = functions,
.function_count = sizeof(functions) / sizeof(functions[0]),
};
return &info;
}
ステップ 2:コンパイル
# macOS / Linux $ gcc -shared -fPIC -I/path/to/hajimu/include -o hello_plugin.hjp hello_plugin.c # Windows (MinGW) $ gcc -shared -I/path/to/hajimu/include -o hello_plugin.hjp hello_plugin.c
ステップ 3:はじむから使う
test.jp を作成して実行します。
取り込む "hello_plugin" として HP
HP["挨拶"]("太郎")
// → こんにちは、太郎さん!
$ nihongo test.jp こんにちは、太郎さん!
プラグイン API
プラグインの開発には include/hajimu_plugin.h をインクルードします。
必須構造体
HajimuPluginFunc — 関数登録用
typedef struct {
const char *name; // はじむ側に公開する関数名(日本語OK)
Value (*fn)(int, Value*); // 関数ポインタ
int min_args; // 最小引数数
int max_args; // 最大引数数(-1で可変長)
} HajimuPluginFunc;
HajimuPluginInfo — プラグイン情報
typedef struct {
const char *name; // プラグイン名
const char *version; // バージョン
const char *author; // 作者
const char *description; // 説明
HajimuPluginFunc *functions;// 関数テーブル
int function_count; // 関数の数
} HajimuPluginInfo;
初期化関数(必須)
すべてのプラグインは hajimu_plugin_init 関数をエクスポートする必要があります。
HAJIMU_PLUGIN_EXPORT HajimuPluginInfo *hajimu_plugin_init(void) {
static HajimuPluginInfo info = {
.name = "プラグイン名",
.version = "1.0.0",
.author = "作者",
.description = "説明",
.functions = functions, // HajimuPluginFunc 配列
.function_count = 関数の数,
};
return &info;
}
関数シグネチャ
すべてのプラグイン関数は同じ型です:
Value 関数名(int argc, Value *argv) // argc: 引数の数 // argv: 引数の配列(argv[0], argv[1], ...) // 戻り値: Value 型
ヘルパー関数
値の作成・操作に便利なインライン関数が用意されています。
値の作成
| 関数 | 説明 | 例 |
|---|---|---|
hajimu_null() |
NULL値を作成 | return hajimu_null(); |
hajimu_number(n) |
数値を作成 | return hajimu_number(3.14); |
hajimu_bool(b) |
真偽値を作成 | return hajimu_bool(true); |
hajimu_string(s) |
文字列を作成(コピー) | return hajimu_string("結果"); |
hajimu_array() |
空の配列を作成 | Value arr = hajimu_array(); |
配列操作
// 配列を作成して要素を追加
Value arr = hajimu_array();
hajimu_array_push(&arr, hajimu_number(1));
hajimu_array_push(&arr, hajimu_number(2));
hajimu_array_push(&arr, hajimu_string("三"));
return arr;
引数の型チェック
static Value fn_example(int argc, Value *argv) {
// 引数の数チェック
if (!hajimu_check_argc(argc, 2)) return hajimu_null();
// 引数の型チェック
if (!hajimu_check_type(&argv[0], VALUE_NUMBER)) {
fprintf(stderr, "エラー: 第1引数は数値が必要\n");
return hajimu_null();
}
double x = argv[0].number;
double y = argv[1].number;
return hajimu_number(x + y);
}
Value の型一覧
| 型定数 | 説明 | フィールド |
|---|---|---|
VALUE_NULL | 空 | - |
VALUE_NUMBER | 数値 | .number (double) |
VALUE_BOOL | 真偽値 | .boolean (bool) |
VALUE_STRING | 文字列 | .string.data, .string.length |
VALUE_ARRAY | 配列 | .array.elements, .array.length |
VALUE_DICT | 辞書 | .dict.keys, .dict.values |
コンパイル方法
すべてのプラットフォームで出力ファイル名を .hjp にします。
macOS
$ gcc -shared -fPIC -I/path/to/hajimu/include -o my_plugin.hjp my_plugin.c
Linux
$ gcc -shared -fPIC -I/path/to/hajimu/include -o my_plugin.hjp my_plugin.c -lm
Windows (MinGW)
$ gcc -shared -I/path/to/hajimu/include -o my_plugin.hjp my_plugin.c
Windows (MSVC)
> cl /LD /I C:\path\to\hajimu\include /Fe:my_plugin.hjp my_plugin.c
Makefile の例
PLUGIN = my_plugin.hjp
SRC = my_plugin.c
INCLUDE = -I../../include
UNAME := $(shell uname -s)
ifeq ($(UNAME), Darwin)
SHARED_FLAGS = -shared -dynamiclib
else
SHARED_FLAGS = -shared
endif
$(PLUGIN): $(SRC)
gcc $(SHARED_FLAGS) -fPIC $(INCLUDE) -o $@ $< -lm
clean:
rm -f $(PLUGIN)
はじむから使う
名前空間付きインポート(推奨)
取り込む "math_plugin" として 数学P // 関数の呼び出し 表示(数学P["二乗"](5)) // → 25 表示(数学P["階乗"](6)) // → 720 表示(数学P["平方根"](144)) // → 12
直接インポート
取り込む "math_plugin" // 関数が直接使える 表示(二乗(5)) // → 25 表示(階乗(6)) // → 720
メタ情報へのアクセス
取り込む "my_plugin" として P 表示(P["__名前__"]) // → "my_plugin" 表示(P["__バージョン__"]) // → "1.0.0" 表示(P["__作者__"]) // → "作者名" 表示(P["__説明__"]) // → "プラグインの説明"
プラグイン検索パス
拡張子なしで 取り込む "名前" とすると、以下の順序で .hjp ファイルを自動検索します。
| 優先度 | 検索場所 | 例 |
|---|---|---|
| 1 | 呼び出し元ファイルからの相対パス | ./plugins/my_plugin.hjp |
| 2 | カレントディレクトリ | ./my_plugin.hjp |
| 3 | ローカルパッケージ | ./hajimu_packages/my_plugin.hjp |
| 4 | グローバルプラグインディレクトリ | ~/.hajimu/plugins/my_plugin.hjp |
グローバルインストール
頻繁に使うプラグインは ~/.hajimu/plugins/ にコピーすると、どのプロジェクトからでも使えます。
# グローバルインストール $ mkdir -p ~/.hajimu/plugins $ cp my_plugin.hjp ~/.hajimu/plugins/ # どのディレクトリからでも使用可能 $ nihongo -c '取り込む "my_plugin" として P; 表示(P["__名前__"])'
対応言語
共有ライブラリを生成できる言語であれば、C以外でもプラグインを開発できます。
要件:hajimu_plugin_init シンボルをCリンケージ(extern "C")でエクスポートし、HajimuPluginInfo * を返すこと。
| 言語 | コンパイル例 | 備考 |
|---|---|---|
| C | gcc -shared -fPIC -o plugin.hjp plugin.c |
標準的な方法 |
| C++ | g++ -shared -fPIC -o plugin.hjp plugin.cpp |
extern "C" でラップ |
| Rust | cargo build --release |
cdylib crate-type、出力を .hjp にリネーム |
| Go | go build -buildmode=c-shared -o plugin.hjp |
//export コメント付き |
| Zig | zig build-lib -dynamic |
出力を .hjp にリネーム |
C++ での例
#include "hajimu_plugin.h"
#include <cmath>
static Value fn_sin(int argc, Value *argv) {
(void)argc;
return hajimu_number(std::sin(argv[0].number));
}
static HajimuPluginFunc functions[] = {
{"サイン", fn_sin, 1, 1},
};
extern "C" {
HAJIMU_PLUGIN_EXPORT HajimuPluginInfo *hajimu_plugin_init(void) {
static HajimuPluginInfo info = {
.name = "trig_plugin",
.version = "1.0.0",
.author = "作者",
.description = "三角関数プラグイン",
.functions = functions,
.function_count = 1,
};
return &info;
}
}
パッケージの公開
作成したパッケージは GitHub で公開できます。
公開手順
# 1. GitHub リポジトリを作成 $ git init $ git add -A $ git commit -m "v1.0.0: 初回リリース" $ git remote add origin https://github.com/ユーザー名/my_package.git $ git push -u origin main # 2. 他のユーザーがインストール $ hajimu パッケージ 追加 ユーザー名/my_package
依存パッケージの管理
パッケージが他のパッケージに依存する場合、hajimu.json の「依存」に記述します。
{
"名前": "my_advanced_package",
"バージョン": "1.0.0",
"説明": "高機能パッケージ",
"作者": "作者名",
"メイン": "main.jp",
"依存": {
"utils": "ユーザー名/utils_package",
"math_extra": "ユーザー名/math_extra"
}
}
依存パッケージは hajimu パッケージ インストール で自動的にインストールされます。
パッケージ管理コマンド
| コマンド | 説明 |
|---|---|
hajimu パッケージ 初期化 |
プロジェクトを初期化(hajimu.json 作成) |
hajimu パッケージ 追加 <URL> |
パッケージをインストール |
hajimu パッケージ 削除 <名前> |
パッケージを削除 |
hajimu パッケージ 一覧 |
インストール済み一覧表示 |
hajimu パッケージ インストール |
hajimu.json の全依存をインストール |
インストール先
| 種類 | パス | 用途 |
|---|---|---|
| ローカル | ./hajimu_packages/ |
プロジェクト固有のパッケージ |
| グローバル | ~/.hajimu/packages/ |
全プロジェクト共通のパッケージ |
Tips & ベストプラクティス
🎯 関数名は日本語で
はじむのユーザーが直感的に使えるよう、関数名には日本語を使いましょう。"square" ではなく "二乗" のように。
🛡️ 引数チェックを忘れずに
hajimu_check_argc() と hajimu_check_type() で引数を検証しましょう。不正な引数でクラッシュするプラグインは避けてください。
📝 メタ情報を充実させる
name, version, author, description をしっかり設定しましょう。ユーザーが P["__名前__"] でプラグイン情報を確認できます。
📦 .hjp はどこでも同じ
.hjp ファイルは OS ごとにビルドする必要がありますが、はじむコード側は一切変更不要です。同じ 取り込む 文で動きます。
完全なサンプルプラグイン
リポジトリの examples/plugins/ に数学関数プラグイン(8関数)のサンプルが同梱されています。
// サンプルで提供される関数 二乗(5) → 25 立方(3) → 27 階乗(6) → 720 フィボナッチ(10) → 55 GCD(12, 8) → 4 平方根(144) → 12 累乗(2, 10) → 1024 絶対値(-42) → 42