複数の秀丸エディタ間での値の共有についNo.38261
fzok4234 さん 20/06/20 10:05
 
お世話になっております。

さて、複数のマクロの実行インスタンスで同じ数値配列や文字列値を共有する方法が
わかりません。

やりたいこととしては、1番目の秀丸エディタでファイルを開いた直後などの自動起
動マクロで数値配列や
複数の文字列などの大量の(数MB程度か)値を動的に生成し、2番目以降の秀丸エディ
タの自動起動マクロから
この値を読み取って利用することです。

マクロにはもともと複数の秀丸エディタで値を共有する静的変数の機能がありますが、
容量が4KBしかなく、
しかも文字列値に限定されているため、意図した用途で使用できないのが現状です。
メモリ上ではなく
ファイルに値を書き込む方法も思いつきましたが、ファイルフォーマットの策定など
でコーディングが煩雑に
なるうえ、読み書き時のオーバーヘッドも大きくなってしまって現実的ではありませ
ん。

外部DLLの導入も含めて現実的な方法があるならばご教示の方よろしくお願いします。


[ ]
RE:38261 複数の秀丸エディタ間での値の共No.38262
でるもんたいいじま さん 20/06/21 02:27
 
こんにちは。秀丸愛用者の「でるもんた・いいじま」です。
4番会議室のほうがよさそうですが、とりあえずこのまま。

> さて、複数のマクロの実行インスタンスで同じ数値配列や文字列値を
> 共有する方法がわかりません。
>
> やりたいこととしては、1番目の秀丸エディタでファイルを開いた直後などの
> 自動起動マクロで数値配列や複数の文字列などの大量の(数MB程度か)値を
> 動的に生成し、2番目以降の秀丸エディタの自動起動マクロから
> この値を読み取って利用することです。

課題が色々とありそうです。
以下、fzok4234さんには既知の内容も多々あると思いますが、一通り丁寧に整理して
みます。

☆ ☆ ☆

1) そもそも秀丸マクロには、数値配列(に限らず文字配列もですが)を外部モジ
ュールに丸ごと渡す方法が用意されていません。

仮に配列の先頭位置へのポインタを取得できたとしても、多次元配列が絡むと一筋縄
ではいかなくなります。(CとFortranの間ですら2次元配列は言語仕様が違いますの
で…。)

強引に文字列変数の中にバイナリデータを詰め込もうとしても、'\0' の扱いとか、
中身がテキストデータという前提での秀丸の内部処理(たとえば\rおよび\nの内部処
理とか、UTF-16でエンコードするならサロゲートペアの結合・分離処理とか)が邪魔
になります。

なので、DLLを書くにせよファイルに記録するにせよ、数値配列は何らかの形で文字
列に変換して保存する必要があります。

数値から文字列にするには sprintf("%d;", #data[#i][#j]) をループで回すのが順
当だと思います。
逆にその文字列を読んで数値に戻すには、1行単位で読み込んでから split( s1, s2,
 s3 ) 関数で文字列の配列に保存して、そのあと適宜 val() で数値に戻します。

#sprintfで書き出す時には、何も考えずに最後の要素の後にもセミコロンを
#置いちゃって大丈夫です。それを読み込んでsplitすると、最後のセミコロンの
#後ろの部分が空文字列として切り出されますが、秀丸の文字列変数にはnullや
#undefinedの類の特殊なものは存在しないので、単純にその要素にアクセス
#せずに無視しておくだけで大丈夫なはずです。

#それともちろん、元から文字列になっているデータを結合する場合は
#セミコロンではなく\x01とか\x7Fとかが無難だと思います。

☆ ☆ ☆

2) 仮にメモリ上に保存する場合、すべての秀丸で関連の処理が終わったときにその
メモリを解放しなければなりません。もし放置しておくと1回数MBの繰り返しが積も
り積もってOSの再起動を要します。マクロが強制終了されたり、あるいは常駐秀丸な
りタスクマネージャーなりから日歩丸ごと落とされたりする可能性があるので、どこ
に書くのかの選択肢があまりありません。

もちろん、逆に処理完了を確信する前に解放するのは論外です。OSを巻き添えにして
落ちる可能性があります。

なので、最初のデータ生成マクロが GlobalAlloc() でメモリを確保してそのハンド
ルを共有変数に保管する、という方法は危険だと思います。

☆ ☆ ☆

結局、私が思いつくのは下の3つくらいです。

●今回のデータ管理(と、必要に応じてそれ以外の各種バックエンド処理も)を行う
ためのEXEファイルをひとつ自作して、そのプロセスのメモリ空間にデータを送り込
む。こうすれば、そのプロセスを落とすだけでメモリは自動的にOSが解放してくれま
す。

#ただしこの場合、そのプロセスとの間のインターフェイス設計が難物です。
#DDEは今では非推奨になっていますし、DLLか何かで強引に SendMessage() を
#使おうにも、別プロセスから受け取った生ポインタにはアクセスできません。

●レジストリに書き込む。書き込むためのデータ生成は sprintf("%08X", #data[#i]
[#j]) で行います。読む際は16進文字列を8バイト単位に切り出して val("0x"+$a)
です。

#この単純なコードの場合、レジストリ上の数値データはビッグエンディアンで
#保存されるので、バイナリのコードからも該当部分にアクセスする場合は
#htonl()、ntohl() をうまく使ってください。

●諦めて %TEMP% フォルダにファイルを作る。そもそも数MB程度なら丸ごとディスク
キャッシュ上に乗るはずですし、最大のメリットとして「不具合が起きても目視で簡
単にデバッグできる」という点もあります。

ちなみにレジストリや一時ファイルの場合、データの生成日時や利用日時など、必要
最低限のデータだけを共有変数に保管するのがいいと思います。その共有変数が未定
義だったり、あるいは日時があまりに古かったりする場合には再度データを生成した
り、あるいは古いデータを単純に消去したりします。

☆ ☆ ☆

以上となります。他にも何かありませんかね…。

[ ]
RE:38262 複数の秀丸エディタ間での値の共No.38265
fzok4234 さん 20/06/21 21:22
 
> 今回のデータ管理(と、必要に応じてそれ以外の各種バックエンド処理も)を行う
>ためのEXEファイルを
> ひとつ自作して、そのプロセスのメモリ空間にデータを送り込む。こうすれば、そ
>のプロセスを
> 落とすだけでメモリは自動的にOSが解放してくれます。

秀丸エディタ側の対応(静的変数の機能拡張や容量改善)がない場合は、この方法での
対策を検討しています。
当方ではよくC#などで.NETプログラミングを行っているため、自作EXEと秀丸エディ
タとのやり取りは.NETの
プロセス間通信機能を利用することになりそうです。


[ ]
RE:38265 複数の秀丸エディタ間での値の共No.38266
秀丸担当 さん 20/06/22 09:36
 

setstaticvariableで他の秀丸エディタと共有できるものは確かに4KBしかなく、不自
由だと思います。
今後サイズを増やすことなどを検討しようと思います。

秀丸エディタの変数は、setactivehidemaruで引き継げることを前提に、もともと他
の秀丸エディタと共有できる仕組みにはなっているのですが、マクロが終了した時点
で全て解放しています。
(ちなみに以前の話題で、これが遅い原因ということがあったので、逆に変数を共有
しないモードとして、V8.92でsetcompatiblemode 0x08000000;を指定することができ
ます)

それで、1つの可能性としては、あるマクロ間では解放せずに別の領域として保持し
続けるという機能追加もできなくはないと思います。
これはいろいろリスクがありそうなので、あくまで案としておきたいところです。

現状では、共通のファイルで扱うのがいいかもしれません。
簡単には、INIファイルでgetinistr/getininum/writeinistr/writeininumがあります。
ファイルの場合、数MBの情報をマクロ上で生成して書き込むというのはそれだけで相
当遅いと思います。
ファイルに効率的に追記していくには#obj=createobject("Scripting.FileSystemObj
ect");からWSHと同じような方法が使えます。
形式や読み取りは、XMLでは#obj=createobject("MSXML2.DOMDocument.3.0");、JSON
では#obj=createobject("html");とかが使えたりするようです。
もし使われる場合は秀丸エディタの文法的なクセが厄介だと思うので、必要であれば
例などを書きます。

最もパフォーマンスがいいのは自作でDLLを作成してそれを呼び出すことだと思います。
DLLを主体として、秀丸エディタの機能を操作するには、DLL側からHidemaru_EvalMac
roを呼び出す方法などがあります。

[ ]
RE:38266 複数の秀丸エディタ間での値の共No.38267
fzok4234 さん 20/06/22 10:22
 
とりあえず現在、自作アプリを作ってプロセス間通信(.NETのIPC)で値を各秀丸エデ
ィタで共有する方向で
話を進めております。

アプリはEXE形式のIPCサーバとDLL形式のIPCクライアントとから成り、それぞれC#で
書いた.NETアプリと
します。サーバは常駐秀丸エディタと同時にWindowsのサインイン時にスタートアッ
プさせておき、サーバ側で
メモリ上に用意したオブジェクト(各要素に名前を付けられるSystem.Collections.Ge
neric.Dictionaryが
妥当か)にクライアントから読み書きを行うという方法です。クライアントDLLの秀丸
エディタからの使用には、
こみやんま氏の「hm.NET.dll」(https://hide.maruo.co.jp/lib/macro/hm_net_v1701.
html)を利用させて
もらいます。

現在の段階は、.NETのIPCの挙動を確認するためのテストコードを作成しているとこ
ろです。


[ ]
RE:38266 複数の秀丸エディタ間での値の共No.38270
fzok4234 さん 20/06/23 05:10
 

>setstaticvariableで他の秀丸エディタと共有できるものは確かに4KBしかなく、不
>自由だと思います。
>今後サイズを増やすことなどを検討しようと思います。

後の投稿でも述べましたが、固定値ではなく「動作環境」からユーザーが自由な値を
設定できるようにした方が良いと思います。


[ ]
RE:38270 複数の秀丸エディタ間での値の共No.38272
秀丸担当 さん 20/06/23 09:49
 

上限は動作環境で指定できたらいいということで、指定できるように検討しようと思
います。

[ ]