DLL共通仕様
本仕様は、SHIORI、SAORI、その他の伺かシステムで使用されるDLLモジュールの共通インターフェースを定義するものである。
メモリ管理
引数/戻り値の受け渡しは全て Windows の Global Memory を使用して行う。具体的には以下の手順で処理を行う:
- ベースウェアは GlobalAlloc() に GMEM_FIXED フラグを指定してメモリを確保し、データを書き込む
- モジュールは受け取った HGLOBAL を (char*) にキャストして直接データにアクセスする
- モジュールは len パラメータを参照してデータ長を取得し、必要なデータを読み込む
- モジュールは GlobalFree() でメモリを解放する
- 処理結果を返す場合、モジュールは新たに GlobalAlloc() で GMEM_FIXED 指定のメモリを確保する
- モジュールは確保したメモリに結果を書き込み、len に新しいデータ長を設定する
- ベースウェアは返却されたメモリハンドルを使用後に GlobalFree() で解放する
注意点:
- GMEM_FIXED フラグ使用時は GlobalLock()/GlobalUnlock() が不要である
- HGLOBAL を (char*) にキャストすることで直接メモリアクセスが可能である
- 渡されたメモリはNULL終端が保証されていないため、必ずlenパラメータを参照してアクセス範囲を制限する
- 戻り値用のメモリは、ベースウェアの実装に依存せず堅牢な動作を保証するため、lenより1バイト多く確保してゼロ終端することが望ましい
request関数
extern "C" __declspec(dllexport) HGLOBAL __cdecl request(HGLOBAL h, long *len);
全てのリクエストは request という唯一の関数で行われる。request関数は伺かモジュールの主要なインターフェースであり、ベースウェアからの全ての要求を処理する。
リクエストデータの形式はHTTPやSSTPのヘッダ形式を参考に設計されており、以下の規則に従う:
- 全ての行はCR+LF(0x0D, 0x0A)で区切られる
- 1行目にはコマンド名とプロトコルバージョンを記載する
- 2行目以降は「ヘッダ名: 値」の形式で任意の数のヘッダが続く
- ヘッダ部の終端はCR+LFを2つ連続して配置(空行の追加)することで示す
- 文字エンコーディングはヘッダで指定された方式(一般的にはUTF-8かデフォルトのOEM codepage)に従う
ライフサイクル関数
DLLロード時およびアンロード時に以下の関数がコールされる。
loadu関数
extern "C" __declspec(dllexport) BOOL __cdecl loadu(HGLOBAL h, long len);
モジュールの初期化を行う関数。
第1引数のグローバルメモリにはモジュールのディレクトリパスがUTF-8エンコーディングで格納される。
SSP 2.6.92 (2025/1/16) より実装された。それより前はloadのみの実装である。
処理内容の例:
- 渡されたパスをカレントディレクトリとして、必要なデータファイルを読み込む
- モジュールの動作に必要なリソースを初期化する
- 必要に応じてログファイルやデータベースの初期化を行う
注意点:
- 文字列データが不要な場合でも、渡されたグローバルメモリは必ず解放する
- 初期化に成功した場合は TRUE を、失敗した場合は FALSE を返却する
- 本関数はベースウェアによって優先的に使用される
load関数
extern "C" __declspec(dllexport) BOOL __cdecl load(HGLOBAL h, long len);
loadu関数の従来版。
第1引数のモジュールディレクトリパスがデフォルトのOEM codepage(日本語環境ではCP932)でエンコードされている以外は、loadu関数と同じ仕様。
注意点:
- loadu関数が実装されていない場合のフォールバック先として使用される
- 互換性確保のため、loadとloaduの両方を実装し、loaduで初期化済の時にloadも呼ばれた場合は無視するのが望ましい
- Unicode対応のためには、受け取ったパスを適切にワイド文字列に変換する必要がある
unload関数
extern "C" __declspec(dllexport) BOOL __cdecl unload();
モジュールの終了処理を行う関数。モジュールのアンロード時にベースウェアから呼び出される。
実装すべき処理:
- CreateFile 等で開いたファイルハンドルを解放する
- CreateMutex 等で作成した同期オブジェクトを解放する
- CreateThread 等で作成したスレッドの終了を待機し、後処理を行う
- その他、モジュールが確保した全てのシステムリソースを解放する
戻り値は現在は使用されていないが、将来の拡張性を考慮して TRUE を返却することが望ましい。