evalmacro を マクロ層とC層に…No.08353
天翔記jp さん 16/09/26 17:34
 
いつもお世話になっております、秀丸マクロ.netの 翔.jp です。

evalmacro という、「文字列をマクロとして(その行に該当内容が記述してあるかの
ように)実行する」といった
ステート(or関数)を作成してはどうでしょうか。

evalmacroは、「マクロ実行中」でのみ実行可能な命令となります。


これ自体は「マクロ層からはあまり役立つものではありません」が、

この「evalmacroと同一制限・同一機能」を
C層(dll層)からも、Hidemaru_EvalMacroに相当する関数を実行可能なように(exeに?)
提供してはどうでしょうか。
(同一制限なので、「マクロ実行中」でのみ実行可能な命令)

これにより、秀丸マクロにのみ提供されていた機能の多くを
C層にも提供したのと同然の効果を得られ、
「dllの中で片付けたい話は、dllで片付けてしまう」といった事が可能となります。



ぜひ、ご検討ください。

[ ]
RE:08353 evalmacro を マクロ層とC層に…No.08354
でるもんたいいじま さん 16/09/26 18:12
 
でるもんた・いいじまです。

空の表示枠の件でつらつらと書いているのですが、先にこちらを簡単に。

> evalmacro という、「文字列をマクロとして(その行に該当内容が
> 記述してあるかのように)実行する」といった
> ステート(or関数)を作成してはどうでしょうか。

> これ自体は「マクロ層からはあまり役立つものではありません」が、

天翔記さんは「DLLから呼び出したい」と考えておられますが、
マクロ層だけからでも使えるとありがたいものがあります。

たとえばEmacsの場合、Emacs Lispのプログラムを編集中に、
編集中のコードの一部分、あるいはキーボードから入力した式を
そのまま実行できます。これは非常に助かります。
秀丸だと、実行したい部分だけを抜粋したファイルを作って、
それを呼び出さないといけません。

あるいはPerlあたりだと、特定のバージョン以降でないと、あるいは
特定のパッケージがインストールされていないとエラー終了してしまう
コードを eval 文で囲んで、その結果が芳しくなければ自前で適切な
エラー処理を行うということができます。

一方で、秀丸でたとえばこんなコードを書いても無意味です。

if (version < 866)
{
    message "秀丸をV8.66以降にバージョンアップしてください。";
    exitmacro;
}
message "コードページは" + str(codepage) + "です。";

このコードは、V8.64以下では「文法エラーです」と言われます。
一応、回避策がないわけではありませんが(バージョン判定だけの
マクロを作って、そこから本体のマクロを呼び出す)、これだけの
ために小さなファイルがひとつ増えるのも面倒なものがあります。

もしかしたら内部的に難しいかもしれませんが、可能であれば
ご検討をお願いします。

[ ]
RE:08354 evalmacro を マクロ層とC層に…No.08355
秀丸担当 さん 16/09/27 16:58
 

evalは、マクロ内から呼び出すのであれば、execmacro相当にするとやりやすい
と思います。
以前にもgotoで分岐先を分けるのにevalができたらいいという話がありましたが、
execmacro相当だとそれはできないので、goto文で文字列指定できるようにした
ことがありました。
eval "goto XXX;"などはできなくて、execmacro相当の呼び出し元のマクロとは
関係ない状態であれば考えられると思います。

DLLから呼び出すとすると、予想できないことが起きる可能性があるのでよく考
える必要がありそうです。
マクロは、setactivehidemaruなどでアクティブの切り替えによってプロセスを
またいで実行の継続ができますが、そういうマクロで問題が起きると思います。
そういう制約があってもよければ、検討できると思います。
他にも問題があるかやってみないとわからないですが、DLLからの呼び出しはデ
リケートなことになると思います。

[ ]
RE:08355 evalmacro を マクロ層とC層に…No.08357
秀丸担当 さん 16/09/28 17:08
 

evalをするとしたら、execmacro相当だと変数が別の空間に変わってしまうので、
変数は同じ空間のほうがよさそうでした。
ただしやはりsetactivehidemaruの切り替えはできないという制約があったほう
が都合がいいです。
そういう方向で検討したいと思います。

[ ]
RE:08357 evalmacro を マクロ層とC層に…No.08358
天翔記jp さん 16/09/28 17:39
 
>
≪全文引用されていたのでコミュニテックス会議室システムが引用部分を省略処理し
ました。≫
>そういう方向で検討したいと思います。
ご検討のほど、ありがとうございます。
よろしくお願いします。

[ ]
RE:08358 evalmacro を マクロ層とC層に…No.08359
秀丸担当 さん 16/09/29 17:05
 

V8.66β7でeval文とDLL用のHidemaru_EvalMacro関数を追加してみています。

[ ]
RE:08359 evalmacro を マクロ層とC層に…No.08365
天翔記jp さん 16/09/30 15:53
 
こちら、かなり強力に機能します。
これがあることで、今まで事実上不可能だったことも可能になっています。
ありがとうございます。


組み込んでみて、Hidemaru_EvalMacroを使おうとすると、
それなりに高確率で遭遇するであろうことがあるので「相談」と「問題提起」の
「間」ぐらいのテイストなんですが、投稿させてもらいます。

■問題概要
 Hidemaru_EvalMacroを使用する際、
 秀丸マクロ環境空間とdll環境空間の値をやり取りするには、
 dll自身に定義した export 関数を経由することになるハズですが、
 この際に、マクロでloaddllしたバインド変数が不明なため、
 マクロ側から、dll側に、loaddllした際の変数名を伝達する必要がある。

 というものです。

 言葉ではわかりにくいので、実際のソースとなります。

-------------------------------------------------------------------------------
#MYDLL = loaddll( hidemarudir + @"\MyDLL.dll" );
-------------------------------------------------------------------------------

さて、ここで、秀丸マクロ層 ⇒ MyDLL.dllへと
filename2を伝達するには

-------------------------------------------------------------------------------
#_ = loaddll( #MYDLL, "SetStrVar", filename2 );
-------------------------------------------------------------------------------
みたいなことが想定されます。

MyDLL.dllは 「int cdecl SetStrVar(TCHAR *sz);」みたいな関数がexportされてい
ることでしょう。

さて、では、秀丸マクロ層から伝達する必要を感じない場合、
即ち、MyDLL.dllはMyDLL.dll自身で、filename2の情報を得たい場合、
以下のようになります。

-------------------------------------------------------------------------------
hm.EvalMacro = Hideamru_EvalMacro  // (Hidemaru_EvalMacroが上手く使えるよう
に定義したメソッドなり関数なりを自前で用意したものとする)

hm.EvalMacro( [[    // [[ ]] はヒアドキュメントのようなものとする
    #_ = loaddll( #MYDLL, "SetStrVar", filename2 );    
]] );
-------------------------------------------------------------------------------

さて、ここで問題が発生するのです、それはdll内で「#MYDLL」と決めうってしまうと、
マクロ上のloaddllの変数名を束縛してしまう、ということです。


■現行、選択肢としては2つ
リファレンスカウンタは増えてしまうが、気にせず、
ぶつからなさそうな名前で、もう一度loaddllする。

同じdllをloaddllなので、リファレンスカウンタだけで増える状態でしょうから、
dll内部状態などは全て維持されます。
若干気持ちが悪いといえば悪いという感じです。

-------------------------------------------------------------------------------
hm.EvalMacro( [[
    #_HIDELOAD = loaddll( hidemarudir + @"\MyDLL.dll" ); ← 実際には、GetMod
uleFileName()みたいなのを使うでしょうが…
    #_ = loaddll( #_HIDELOAD, "SetStrVar", filename2 );    
]] );
-------------------------------------------------------------------------------

もうひとつの考え方は、dllで束縛したシンボル名をdllに伝えるというものです。
-------------------------------------------------------------------------------
#MYDLL = loaddll( hidemarudir + @"\MyDLL.dll" );
#_ = dllfunc( #MYDLL, "SetBindSelfSimbol", "#MYDLL" );
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
hm.EvalMacro( [[
    #_ = loaddll( %s, "SetStrVar", filename2 );    // %sにSetBindSelfSimbol
関数で渡した文字列が入ってるものとする
]] );
-------------------------------------------------------------------------------

いずれにしても、いかに「#MYDLL」を得るのか、
(もっといえば、loaddll関数ではなく、loaddll文もあるのですが、まぁそこはス
ルーするとしても)
  「どのように変数に束縛されたのか」を得るのか、ですねぇ〜

このあたりをスマートに解決できないものかなぁ、といったところです。

[ ]
RE:08365 evalmacro を マクロ層とC層に…No.08366
天翔記jp さん 16/09/30 15:55
 
× : #_ = loaddll( #MYDLL, "SetStrVar", filename2 );
○ : #_ = dllfunc( #MYDLL, "SetStrVar", filename2 );

[ ]
RE:08366 evalmacro を マクロ層とC層に…No.08367
秀丸担当 さん 16/09/30 17:08
 

早速ご確認ありがとうございます。
現状Hidemaru_EvalMacroは少々無理をしてやっている感があり、安定にしたいと
ころです。早速execmacroがうまくいかない問題が見つかっていて、次で修正し
ます。
さらに仕組みを設けると不安定になりそうなこともあり、既に試されている通り、
dllfuncで変数名を知らせるなど方法などでしていただけたらと思います。

[ ]
RE:08367 evalmacro を マクロ層とC層に…No.08371
天翔記jp さん 16/10/01 02:42
 
そうですね。
やはりjumpを挟むものや、環境が飛んでしまうものは無理があるだろうな、
とは思ってはいました。


今回のHidemaru_MacroEvalの提供は、
C言語から実行できるようになったとか言った話にはとどまりません。

その真の実態は、
「インプロセスであれば、秀丸マクロは、
『どのような言語からでも実行可能となった』」
ということに他なりません。

今までのマクロスタンスは「秀丸マクロから他のスクリプト言語やdllを呼び出す」
スタイルだったのが、

「好きな言語、得意な言語」でプログラムの骨格全体を作り、
秀丸独自仕様に用があるその部分だけ、(得意言語の記述の中に)マクロをEvalで埋め
込めばよい、
といった形に出来るようになったのは非常に大きいと思います。





[ ]