8. SAORI呼び出し
SAORIを使っているゴーストは、呼び出し部分の書き換えが必要です。書き方は簡単になりますが、戻り値の扱いと呼び出しの制限に、里々とは違う点があります。
呼び出し方
里々では、satori_conf.txt の @SAORI に登録名を書き、(登録名,引数,…) で呼びました。
@SAORI
mciaudio,saori/mciaudio.dll
(mciaudio,load,鳥の詩.mp3)(mciaudio,play)
湊では、登録は不要です。saori("DLLのパス", 引数, …) と、パスを直接書いて呼びます。
OnBoot => {
let r = saori("saori/mciaudio.dll", "load", "鳥の詩.mp3")
let r2 = saori("saori/mciaudio.dll", "play")
}
- パスは
ghost/masterからの相対パスです。区切りは/でも\でも構いません。 - 絶対パス(
C:\…、/…)、..を含むパスは使えません。エラーになります。 - DLLは、初回の呼び出し時に読み込まれ、ゴーストが終了するまで保持されます。同時に保持できるDLLは32個までで、超えると最も使っていないものから解放されます。
- 引数は、数値も真偽値も、表示形式の文字列に変換されて渡されます(
3→"3")。 - 湊本体とビット数が同じDLLでないと読み込めません。
里々の呼び出しを湊に直すと、(登録名,a,b) → saori("パス", "a", "b") です。呼び出しごとにパスを書くのが面倒なら、func で包みます。
func 音楽(cmd, arg) {
return saori("saori/mciaudio.dll", cmd, arg)
}
戻り値は配列
saori() は、SAORIの戻り値を配列で返します。Value0 が [0]、Value1 が [1] です。里々の (S0) (S1) に当たります。
検証のために、次のように返す小さなSAORI(echo.dll)を作りました。
| 戻り値 | 内容 |
|---|---|
Result | echo: + Argument0 |
Value0 | Argument0 を大文字にしたもの |
Value1 | 引数の個数 |
Value2 | 全引数を / でつないだもの |
これを湊から呼びます。
OnBoot => {
let r = saori("echo.dll", "abc", "d e", 3)
湊: len=${len(r)} r0=${r[0]} r1=${r[1]} r2=${r[2]}
}
実際に動かした結果は、次のとおりです。
\0len=3 r0=ABC r1=3 r2=abc/d e/3\e
r[0] は Value0(ABC)、r[1] は Value1(3)、r[2] は Value2(abc/d e/3)です。
Result は取り出せないことがある
上の結果で、Result(echo:abc)はどこにもありません。湊は、Result を Value0 とは別に取り出せません。 SAORIが Value0 を返さないときにだけ、Result が [0] に入ります。Value0 があれば、そちらが優先されます。
里々の (登録名,引数) は、SAORIの Result を、括弧の位置に埋め込む文字列にしました。湊で同じことをするには、その SAORI が Value0 を返さないか、Value0 に欲しい値が入っている必要があります。
| SAORI の戻り | 湊で取れるもの |
|---|---|
Result だけ | r[0] = Result |
Result と Value0… | r[0] = Value0、r[1] = Value1… (Result は取れない) |
Value が無く Result も無い | 空の配列 |
ssu.dll のように、Result に個数を、Value0 以降に分割結果を返すSAORI(split など)は、r の要素がそのまま分割結果なので、個数は len(r) で分かります。
Result と Value0 の両方が必要なSAORIを使っているなら、13. 段階移行で述べる別の方法を検討してください。
SAORIが何も返さないとき
返る配列の要素数は、SAORIが返した Value の数で決まります。検証用の echo.dll を引数なしで呼ぶと、Value0 が空文字列の3要素の配列が返りました(SAORIが空の値を返したため)。戻り値の有無に依存した処理は、len(r) で確かめてください。 存在しない番号を参照すると null になり、警告が出ます。
呼び出しの制限
SAORIの呼び出しは、湊がSSPからの要求に答えている最中に同期して行われます。SAORIが応答しないと、SSP全体が止まってしまうため、湊は次の制限を設けています。
| 制限 | 内容 |
|---|---|
| 1イベントあたり10回まで | saori() と get_property() の合計です。ループの中で呼ぶと、11回目以降は呼び出されず、空の配列(get_property は空文字列)が返ります。saori() では警告が出ますが、get_property() では警告は出ません(debug_log が有効なときのログにだけ残ります) |
| 応答は5秒まで | 5秒待っても返らないと打ち切ります。打ち切られたSAORIは、そのゴーストを再読み込みするまで二度と呼び出されません |
| 読み込みエラー | DLLが見つからない、必要な関数がない、パスが不正(絶対パス、.. を含むなど)の場合は、エラー(error)を出して空の文字列を返します(配列ではありません)。len(r) は 0、r[0] は null で警告が出ます |
ループから呼んだときの結果です。
OnBoot => {
for (let i = 0; i < 12; i++) {
let r = saori("echo.dll", "x")
湊: [${r[1]}]
}
}
\0[1][1][1][1][1][1][1][1][1][1][][]\e
10回目までは結果が入り、11回目・12回目は空になります。
里々のSAORI呼び出しには、こうした回数制限はありませんでした。1回のトークで何度もSAORIを呼ぶ処理は、まとめて1回で済むように作り直してください。
文字コードとヘッダ
- 湊はSAORIに、引数を UTF-8 で送ります(
Charset: UTF-8)。応答も UTF-8 として読みます。 - SAORI/1.0 の
Sender、SecurityLevelなどのヘッダは付けません。 - DLLを読み込むときにSAORIへ渡すパスは、Shift_JIS(表せない場合はUTF-8)です。
古いSAORIには、リクエストの Charset ヘッダを見ずに Shift_JIS で処理するものがあります。 そうしたSAORIに日本語の引数を渡すと、文字化けや誤動作の原因になります。実際に使うSAORIごとに確認してください(このガイドでは、実在するSAORIとの組み合わせは確認していません)。
get_property
里々の %property[…]、および環境変数の取得に当たるのが get_property("…") です。SSPのプロパティシステムに、SSTP(127.0.0.1:9801)で問い合わせます。
OnBoot => {
湊: ${get_property("currentghost.name")}
}
- 結果は文字列です。取得に失敗したときは、空文字列です(SSPが起動していない環境では、常に空です)。
- 1イベントあたり10回の上限には、
saori()と合わせて数えられます。 - 同期呼び出しのため、SSPの状態によっては、SSPの動作を一瞬止めることがあります。頻繁に使わないでください。
YAYAから来た方へ
- YAYAの
FUNCTIONEX('saori\x.dll', 引数…)は、saori("saori/x.dll", 引数…)に当たります。パスの基準が違う点(YAYAはyaya.dllからの相対、湊はghost/masterからの相対)は、shiori.dllと同じ場所に置いていれば同じです。 - YAYAでは、
Resultが関数の戻り値、Value0…がvalueex0…に分かれて入ります。湊では両方が1つの配列にまとまり、ResultはValue0があると取れません。 YAYAでResultを使っていたコードは、そのままでは移せません。
次は9. セーブデータの移行と型の違いに進んでください。