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)を作りました。

戻り値内容
Resultecho: + Argument0
Value0Argument0 を大文字にしたもの
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. セーブデータの移行と型の違いに進んでください。