TTXBind()関数の引数 Version の仕様
そうですね。 5.0でTTXの互換性が一部無くなったので、両対応のTTXを作れるようにする為にもバージョンを上げるいい機会だと思います。
新しいバージョンが出るたびに上げていくかは検討が必要だと思います。
毎回上げるとすると、5.0で50だと5.10が出た時に問題になるので500スタートの方がいいでしょうか。 59 -> 510 でも大小関係は保たれるのでそれでいいのかもしれませんが。
毎回上げず、互換性に影響がある変更があった場合のみ上げるようにするならば50から1ずつ増やすので問題ないでしょう。
一番の目的は、4.106 以下と 5 以降の分離だと思います。
理想は「毎回上げず、互換性に影響がある変更があった場合のみ上げる」なのですが、 何をもって「互換性に影響がある変更」とするかが問題と思います。
TTXでの互換性は、バイナリ互換であってほしいので対象は以下と考えられます。
TTX API の互換性で見たら (1)-(3) といったところでしょうか。この範囲内なら50 から 1 ずつ増やすでもよさそうです。
(4) も互換性の有無は判別できるとは思いますが、リリース直前まで上げるのか上げないのか迷いそうです。
(5)-(6) も含めるなら、互換性の管理は難しいため、毎回上げてTTXプラグイン側に判断を丸投げといったところだと思います。
PTTSet の RunningVersion は、構造体中のオフセットが最後のほうにあり、 今後リリース時にオフセットが異なってしまう可能性があります。 それならば、毎回上げて TTX プラグイン側で判断したほうがよさそうです。
ちなみに v4.106 と v5.0alpha(r9858) のバイナリ互換は LogDefaultName[] までとなります。 (LogDefaultPath[] が *LogDefaultPathW となったため)
よって、自分の見解では 引数の Version は、 RunningVersion のように自動で計算させたほうが後々面倒がないのではと思っています。
RunningVersion は、メジャーバージョン *10000 としていますが、引数の Version は、 WORD 型(2バイト分)なので、 *1000 か *100 くらいで良いと思います。
マイナーバージョンが 100 を超えると読みにくく、 *10 では心もとないので *100 (500スタート)のほうが良いのではないでしょうか。
バージョン間の差分を簡易的に調べてみたので添付します。
ちなみに v4.106 と v5.0alpha(r9858) のバイナリ互換は LogDefaultName[] までとなります。 (LogDefaultPath[] が *LogDefaultPathW となったため)
がんばって互換性を維持しても無駄になるかもしれませんが、これは構造体の途中にメンバを追加したり、削除・変更したりするのではなく、追加するなら一番最後にし、使わなくても予約として残す、というお作法を破っている感じですか?(むかし何か追加したときに注意されたような記憶が…)
そうですね。お作法は破られていますね。
お作法通り、追加するなら一番最後とするのが下位互換性を保てて良いかと思いますが、v4.xx の間にも何度か構造体のバイナリ互換性は失っています。
「Tera Term 5 について」https://ttssh2.osdn.jp/manual/5/ja/usage/migrate_to_5.html にて、
最後の行に「まだ変化する予定(メンバ名、順序、サイズ、型などなど)。」とあるので、
パス名が固定長配列から動的配列に移行したり、今後も構造が変わり、バイナリ互換性は失うと推測されます。
考え方を変え、お作法守るよりは、ビルドは最新のみとし、できるだけ下位互換性を得られるように
構造体のマッピング変換機能を持たせるようにしてみました。
テスト用のプラグインのソースコードを添付します。(TTXTest_TTTypes.zip)
配列サイズが異なったり、細かい個別案件はあるものの 8 割くらいは、下位互換性を持たせられると思います。
v5.0 でビルドしたプラグインを v2.3 の環境にもっていってもボーレートの値 (ts->Baud) を取得できます。
プラグインが使用する構造体のメンバーは通常ほんの一部しかないのと思うので、プラグインの下位互換性を考慮して
構造体の変更にブレーキをかけるよりは、健全かなと思います。
構造体のバイナリ互換をあまり気にしなくなっても、大きく変更したらやはり互換性を保てなくなるので なんでもできるわけではないのですが。。。
r9922 で LogDefaultPathの領域をリザーブとして確保するようにしました。
ANSI文字列でパスを入れていないので ここを参照しているプラグインがあると正常に動作しないことになります。 この対応では不十分ですね。
ひとまずは、このメンバー以降のオフセットが同じになったはずです。
Unicode,ANSI両方の文字列が準備されているメンバーもあるじゃないか、 と思われると思います。 互換性を持たせるためというのもありますが、 まだ作業中で手がついていない状態というのもあります。 できるところからやっていっています。
Tera Term プロジェクト内のソースでは LogDefaultPathは参照していなくて、 LogDefaultPathW を使っています。このメンバーについてはUnicodeへ移行した状態ですね。
プラグインの、バイナリ互換はちょっとしんどくて、ソース互換な感じで考えるのがよさそうかなと思います。
提案いただいている方法まだ見れていません。考えてみますね。
他にも直したほうがよいところがあったら指摘ください。
| ひとまずは、このメンバー以降のオフセットが同じになったはずです。
修正ありがとうございます。 オフセットは同じになるように調整されてることを確認しました。 簡易解析なので、ビルドして動作確認してみないととだめですが、とりあえずチェック結果だけ報告します。
ただ、すぐに EtermLookfeel の事前領域確保対応によるオフセットずれになるのあまり差はないと思われます。
各バージョンのオフセット比較用データも添付します。(dataフォルダ下、v5_0がr9903でv5_1がr9922に相当)
| プラグインの、バイナリ互換はちょっとしんどくて、ソース互換な感じで考えるのがよさそうかなと思います。
そうですね。全体として決まれば、ソース互換でもよいのでないでしょうか。
| EtermLookfeel の事前領域確保対応によるオフセットずれ
対応したのを思い出しました(r9109) trunk(Tera Term 5)では対応していません。
eterm_lookfeel_t のメンバーを1つ減らせれば、 構造体でまとめた状態+互換性がある状態にできるか?・・
eterm_lookfeel_t のメンバーを1つ減らせれば、 構造体でまとめた状態+互換性がある状態にできるか?・・
バイナリ互換も目指すなら、構造体(eterm_lookfeel2_t)を追加して、追加分を最後に移動すればよいのではないでしょうか (a.patch)
次の範囲で互換性があるといえると思います。
r10134 でかなりオフセットのずれがなくなったのではないかと思います。
バイナリ互換の話も出てきたりして、 チケットのタイトル(TTXBind()関数の引数 Version の仕様)よりも内容が広がってきています。
とりあえずバージョンを500にしてTera Term5(alpha)でも4でもつかえるつかえる プラグインを作れる状態にするのはどうでしょう?
確認:trunk/r10134
オフセットのずれはかなりなくなりました。 ソースコード互換とのことでしたので、オフセットずれはあってもしかたないかなと思っていましたが、ずれは少ない方が複数のバージョンで同じバイナリのプラグインを使えるのでありがたいです。
■ v5.0 とのオフセット比較
tttset 構造体
TComVar 構造体
とりあえずバージョンを500にしてTera Term5(alpha)でも4でもつかえるつかえる プラグインを作れる状態にするのはどうでしょう?
500 でいいのではないでしょうか。 Tera Term5(alpha) で API のバージョンを識別出来れば、動的に切り替えることが可能と思います。
簡易的なバージョン間の差分を添付。
バージョンを示す定数/変数(ビルド時にわかる/動作時にわかる)は次の通り
TTVERSION をプラグインのバージョンを表す値、
と定義すれば、 この値でビルド分けして、TTXBindの第一引数で動作を分ければ 1つのソース/バイナリで4,5どちらでも動作するものを作れそうな感じです。
調べたところ TTVERSION は、Tera Term本体では使っていないようです。
プラグインのバージョンとして意図された define だと思います。
ttplugin.h に移動して、「プラグインのバージョンです」とコメントを入れて、500に変更すればよさそうです。
r9304 で cygterm_t にリザーブを追加していました。 その分構造体サイズがずれていますね。
cygterm_t のファイル名をUnicode対応にすることも考えてみます。
TTVERSION は、オリジナルTeratermの最終バージョン 2.3から変えていないだけだと思います。
tttset.RunningVersion は、v4.105 から導入されてますがオフセットが変わってしまっていたため、プラグインのバージョン判別には使っていませんでした。
Teraterm5以降は、Bind()のversion引数(≒TTVERSION()で新旧判別して新ならtttset.RunningVersionを確認するのはありだと思います。
r10179 で cygterm_t を tttset から分離しました。
確認:trunk/r10181
cygterm_t が reserved 領域になったことで tttset のほぼ最後までオフセットが同じになりしました。 添付した比較データは更新しました。
チェックありがとうございます。
ひとまずクローズしようと思います。
何かあったら再度オープン/別チケットで対応しましょう。
TTXプラグイン登録時 TTXBind() 関数呼び出しの引数 Version は以前から 23 となっている。
特に意図していないなら Teraterm Pro version 2.3 を指す?23ではなく、動作するTeratermのバージョンを指定してもよいのではないでしょうか。