ヘッダーファイルemacs-module.hのインクルードとGPL互換性シンボル(GPL compatibility symbol)によりモジュールの記述を始めましょう:
#include <emacs-module.h> int plugin_is_GPL_compatible;
Emacsインストールの一部としてシステムのインクルードツリーにemacs-module.hファイルがインストールされます。かわりにEmacsのソースツリー内で見つけることもできます。
次にモジュール用の初期化関数を記述します。
int
emacs_module_init (struct emacs_runtime *runtime)
¶Emacsはモジュールをロードする際にこの関数を呼び出す。モジュールがemacs_module_init
という名前の関数をエクスポートしていなければモジュールはエラーをシグナルする。この初期化関数は初期化成功時には0、それ以外は非0をリターンすること。後者の場合にはEmacsはエラーをシグナルして、モジュールのロードは失敗する。初期化中にユーザーがC-gを押下すると、Emacsは初期化関数のリターン値を無視してquitする(quitを参照)(必要なら初期化関数内でユーザーのquitをcatchできる。should_quitを参照)。
引数runtimeは2つのパブリックなフィールドを含むCのstruct
へのポインター、size
はその構造体のバイトサイズ、get_environment
はEmacsの環境オブジェクトとそのインターフェースにモジュール初期化関数をアクセス可能にする関数へのポインターを提供する。
初期化関数はモジュールに必要な初期化は何であれすべて行うこと。さらに以下のタスクを行うことができる:
モジュールにコンパイルされたruntime構造体のsize
メンバーの値を比較することにより、モジュールをロードするEmacs実行可能形式がモジュールと互換性があるか検証できる。
int emacs_module_init (struct emacs_runtime *runtime) { if (runtime->size < sizeof (*runtime)) return 1; }
モジュールに渡されたruntimeオブジェクトのsizeが期待する値より小さければ、ロードしようとしているモジュールがEmacsの新しい(最近の)バージョン向けにコンパイルされていることを意味する(そのモジュールはEmacsのバイナリーとは非互換かもしれない)。
さらにモジュールは期待しているモジュールAPIの互換性も検証できる。以下の例では上述のemacs_module_init
関数の一部であることを仮定している:
emacs_env *env = runtime->get_environment (runtime); if (env->size < sizeof (*env)) return 2;
これはAPIの環境(environment)へのポインターの取得用に構造体runtime
(size
フィールドに構造体のバイトサイズも保有するCstruct
)で提供されるポインターを使用してget_environment
関数を呼び出す。
最後にEmacsから渡された環境のサイズと既知のサイズを比較することによって、以下のように古いバージョンのEmacsで動作するモジュールを記述できる:
emacs_env *env = runtime->get_environment (runtime); if (env->size >= sizeof (struct emacs_env_26)) emacs_version = 26; /* Emacs 26 or later. */ else if (env->size >= sizeof (struct emacs_env_25)) emacs_version = 25; else return 2; /* Unknown or unsupported version. */
新しいバージョンのEmacsではメンバーを環境に常に追加して削除は決して行わないので、新たなEmacsのリリースではサイズは増加するだけであることにより機能する。与えられたバージョンのEmacsにたいして、そのバージョンに存在するモジュールAPIは新しいバージョンのものと等しいので、その部分だけを使用できる。
emacs-module.hはプリプロセッサマクロEMACS_MAJOR_VERSION
を定義する。これはヘッダーがサポートするEmacsの最新バージョンとなる整数リテラルに展開される。バージョンの情報を参照のこと。EMACS_MAJOR_VERSION
はコンパイル時の定数であり、モジュールをロードしたカレントで実行中のEmacsのバージョンを表さないことに注意。emacs-module.hやEmacsの種々なバージョンにたいして互換性をもたせたければ、EMACS_MAJOR_VERSION
にもとづいた条件コンパイルを使用できる。
モジュールが処理全体を初期化関数内で行い、Lispオブジェクトにアクセスしたり環境構造体を通じてアクセス可能なEmacs関数を使用することがない場合を除いて、モジュールの互換性検証を常に行うことを推奨する。
これはLispコードが名前で呼び出せるようにモジュール関数に名前を与える。これを行う方法については以下のモジュール関数の記述で説明する。