HmOutputPanel.dll と Output関数No.10318
vscode-life さん 21/02/23 19:58
 
ヘルプより
-----------------------------------------------------
アウトプット枠(HmOutputPane.dll)
Output
文字列を出力します。
複数行の文字列を一度に出力する場合は改行コードを"\r\n"として記述する必要があ
ります。
成功時は0以外、失敗時は0を返します。
dllfunc用の関数ですが、Unicodeも扱うことができます。(内部的な特殊なやりとり
をしています)
dllfuncwで呼び出すことはできません。
-----------------------------------------------------

3年ぐらい前でしたか、同じ話が出た時、話を進展させずに失敗したと思っています
が、

上記dllとOutput関数は、
Unicode文字(wchar)を(も)引数に渡すにもかかわらず、
呼び出しがdllfuncのままであり、使い方が歪んでいます。
(歴史的な経緯なのでしょう。まぁそこはもう仕方がないとして…)

この関数はマクロからは内部的に特殊な処理をすることで、なぜかUnicodeが扱えま
すが、
インプロセスでの外のプログラムは、その特殊な処理が不明なため、SJIS/Ansiしか
扱えません。

これは現代のほとんどの2021年上位主流のプログラミング言語のデフォルトの想定文
字セットと乖離してしまっているので、
Unicode/wchar_t を伝達できるようにしておいたほうがいいと思います。

可能であれば、マクロからでも
dllfuncw(#dll, "Output", $unicode.... )
とちゃんと合わせた記述も受け入れたほうがいいと思いますが、
(dllfuncの方は影響が大きいのでこれまでのansi/unicode両対応のまま)

歴史的な経緯があり、難しいということであれば、
dllfuncw(#dll, "OutputW", $unicode.... )
を新設し、マクロ以外からでも(インプロセスの)dllなどから、この関数を使って、
アウトプットへ
Unicodeの文字列を送信できる、というのを提案します。

[ ]
RE:10318 HmOutputPanel.dllと Output関数No.10319
でるもんたいいじま さん 21/02/24 03:08
 
でるもんた・いいじまです。

vscode-lifeさんとは以前にモメたことがあるのですが、歴史的なことについては私
のほうが詳しい部分もあると思うので、今回は分かる範囲で。
釈迦に説法な部分もあるはずですが、行き違いがないように丁寧に書いてみました。

> 上記dllとOutput関数は、
> Unicode文字(wchar)を(も)引数に渡すにもかかわらず、
> 呼び出しがdllfuncのままであり、使い方が歪んでいます。
> (歴史的な経緯なのでしょう。まぁそこはもう仕方がないとして…)

> この関数はマクロからは内部的に特殊な処理をすることで、
> なぜかUnicodeが扱えますが、

まさに歴史的経緯ですね。

詳細は変換モジュールを作りたい人向けの資料に書いてあるとのことですが(スミマ
セン、私もまだ読んでいません)、種明かしは簡単なはずです。
秀丸内部ではUnicode文字を「ANSI文字列には登場しないバイト列」にエンコードし
て収納している(大雑把なイメージとしてはGB18030に近い)、DLLにもその形のまま
渡している、ただそれだけのはずです。
関数呼び出しの際に特殊な情報が裏ルートで渡るわけではないです。

ちょっとした頭の体操としてぜひ、下記のサンプルコード(我ながら汚いなあ…イマ
ドキの人ならもっと簡潔・安全に書けそう)を叩き台にしてテスト用DLLを書いてい
ただいて、マクロからdllfuncstr(wのつかないほう)でUnicode文字列を渡してみて
ください。

//---------------
#define HEXDUMP_MAXLEN 100000 //この数字はテキトーに決めてください
static char buffer[HEXDUMP_MAXLEN*3+1]; // 秀丸の要請によりstaticが必要
#define NO_FURTHER (buffer+HEXDUMP_MAXLEN*3)

__cdecl char *StringHexDumpA(const unsigned char *s)
{
 unsigned char c;  // この値をsprintfの%Xに渡すので、unsignedと明示
 char *p = buffer; // sprintfの型定義に従い、こちらは符号指定なし
 size_t ret;
 while ( 1 )
 {
  c = *s++;
  ret = sprintf(p, "%02X ", c);
  #ifdef DEBUG
  if ( ret!=3 ) { return "sprintf()!=3. Buffer may be broken."; }
  #endif
  p += 3;

  if ( c==0 ) { p[-1]=0; break; }
  if ( p == NO_FURTHER ) { p[-1]='!'; break; }
 }
 return buffer;
}
//---------------

> これは現代のほとんどの2021年上位主流のプログラミング言語の
> デフォルトの想定文字セットと乖離してしまっているので、
> Unicode/wchar_t を伝達できるようにしておいたほうがいいと思います。

これは同意見です。

> 可能であれば、マクロからでも
> dllfuncw(#dll, "Output", $unicode.... )
> とちゃんと合わせた記述も受け入れたほうがいいと思いますが、
...
> 歴史的な経緯があり、難しいということであれば、

結論から言えば、「秀丸内部とマクロからだけOutput()が呼ばれる」という前提なら、
そしてその時のみ、この仕様は安全な形で実現可能だと思います。
その前提のもとでなら、Output()内部からHidemaru_GetDllFuncCalledType(1) を呼
べばdllfuncとdllfuncwのどちらで呼ばれたかが分かるので、それで判別できそうです。

ただ、ご希望の内容は
> マクロ以外からでも(インプロセスの)dllなどから、
> この関数を使って、アウトプットへUnicodeの文字列を送信できる、
ということですから、この方法で行くためには
@インプロセスDLL→Output()→Hidemaru_GetDllFuncCalledType(1) と呼ばれた際の
返り値をDLLから恣意的に操作するためのトリック
A逆に、秀丸本体のコードがOutput()を呼んだ際に、副作用で「インプロセスDLL→H
idemaru_GetDllFuncCalledType(1)」の呼び出し結果がデタラメになることがないよ
うにするためのトリック
が必要になります。

そうなると、今でさえ屋上屋を重ね続けている秀丸本体がスパゲッティ化すること必
至ですし、DLL作者の側でもその呪文を毎回唱えるのが面倒になります。
(で、たとえば L"ABC" のつもりで 41 00 42 00 43 00 00 00 というバイト列を渡
しても、関数側はchar[]だと思っているので最初の 'A' だけしか見てくれない、と
いう罠にハマる。)

そもそも、多重定義でない単一の関数を相手に配列の生ポインタを受け渡しするにも
関わらず、その配列の型が何であるかを関数に自動判別させる、という時点で無理筋
です。
渡すものが生の配列でなくて構造体ならどうにでもなりますが、今回は「wchar_tを
渡す時は先頭にBOMをつける」という不自然な方法しか思い浮かびません。

というわけで結局、
> dllfuncw(#dll, "OutputW", $unicode.... ) を新設し、
という方法が明快で紛れもなく、安全確実なように思います。

ちなみに、
> (dllfuncの方は影響が大きいのでこれまでのansi/unicode両対応のまま)
という言い方は少し語弊があるかも。「両対応」つまりint8_t[]とint16_t[]の両方
を受け付けるのではなく、渡されるものはあくまでも常時int8_t[]です。

ではでは。

[ ]
RE:10319 HmOutputPanel.dllと Output関数No.10320
秀丸担当 さん 21/02/24 11:45
 

でるもんたさんいいじまさんが言われる通り、dllfuncを前提としている関数は、DLL
側でHidemaru_GetDllFuncCalledTypeで呼ばれ方の判断ができることになっています。
現状で、Output関数内では、Hidemaru_GetDllFuncCalledTypeのチェックはしていな
いです。

外部DLLから直接Outputが呼ばれるという想定だとしたら、将来的にOutput関数内でH
idemaru_GetDllFuncCalledTypeでチェックすると、動作できなくなるかもしれません。
そうなると、OutputWという別関数名で、将来的にもHidemaru_GetDllFuncCalledType
でチェックすることは無いという約束をしないといけなくなります。

外部DLLからの想定ではなく、マクロ上から呼ばれるという想定だとしたら、どちら
でもいけると思いますが、マクロファイル上の記述がdllfuncではなくdllfuncwにで
きるという、モヤモヤが晴れるくらいの効果にはなると思います。

Outputではないですが、dubuginfoでアウトプット枠に出力する方法もできるように
してありました。
debuginfo 2;をあらかじめしておくと、debuginfo "abc";でアウトプット枠になりま
す。
外部DLLから呼ばれる想定だとすると、Hidemaru_EvalMacro("debuginfo \"テキスト\
";")とするとUnicodeでやりやすいかもしれません。

[ ]
RE:10320 HmOutputPanel.dllと Output関数No.10321
でるもんたいいじま さん 21/02/24 12:00
 
でるもんた・いいじまです。一つだけ。

> Outputではないですが、dubuginfoでアウトプット枠に出力する方法も
> できるようにしてありました。
> debuginfo 2;をあらかじめしておくと、debuginfo "abc";でアウトプット枠になり
>ます。
> 外部DLLから呼ばれる想定だとすると、
> Hidemaru_EvalMacro("debuginfo \"テキスト\";")
> とするとUnicodeでやりやすいかもしれません。

これはこれで、「テキスト」の部分に " や \ がある場合にはエスケープする処理が
必要で、結局ラッパー関数を自前で書くことになりそうです。「テキスト」の長さと
出力頻度次第では、文字列連結のオーバーヘッドも気になります。

私自身が使うわけではありませんが、やはり OutputW() を推しておきます。

[ ]
RE:10321 HmOutputPanel.dllと Output関数No.10322
秀丸担当 さん 21/02/24 15:20
 

マクロから呼ばれる想定であれば、OutputWがあってもいいと思いますが、マクロの
書き方がすっきりするくらいの効果しかないことになります。

DLL側から直接呼ばれる想定であれば、OutputWは、将来もHidemaru_GetDllFuncCalle
dTypeでチェックしないという約束をしなくてはいけなくなってしまいます。
これもまた特例を作ることになり、好ましくない気がします。

それを回避する何らかのトリックを用意するのも手ですが、どんどん複雑化しそうで
す。

dllfunc用ではなく、DLL側から呼ばれる用の関数(Hidemaru_*)を増やすのであればあ
りだと思います。
例えばHidemaru_Logみたいな関数を新設してアウトプット枠にも出力できるようにす
るとか。

[ ]
RE:10322 HmOutputPanel.dllと Output関数No.10324
vscode-life さん 21/02/24 15:38
 
 おふたりとも返答ありがとうございます。

Hidemaru_GetDllFuncCalledType うんぬんについては、私が引数を型を問わないvoid
 *にして受け取ったり返したりするため、実装してもらったものなので、
(多分日本で一番この仕組の味を出して使ってるのも私でしょう...)


ーーーーーーーーーーーーーーーーーーーーーーー

話が若干みえにくいので、明確にしておきたいのですが、
以下はすべてインプロセスのdllの話です。
(マクロの話はとりあえず話を出来る出来ないをややこしくするので除外、プログラ
ムからevalの話も抜き(それはマクロが一瞬走るため))


■以下を明確にしたいです


・現状、HmOutputPanelの「Output関数は」、引数として何らかのバイト列を与えると
 元がUnicodeの文字列であっても再現する方法がある(or ない)

・それはどこかに資料として存在する(or しない)
 https://hide.maruo.co.jp/software/hidemaruold.html
 変換モジュール開発キットおよびサンプル変換モジュールはこちら

・そのOutput枠が認識する特殊な渡し方は、でるもんた・いいじまさんが示す
 「文字列はバイト列である」が各バイトをバイト「値」ではなく「文字」に変換し、
 さらに文字と文字と空白で連結したもの

 このような記述そのままが出来る言語は存在しないでしょうが、しゅしはまぁ
 byte[] data = Encoding.Unicode.GetBytes(str);
 string[] data = data.foreach((c) => sprintf("%02X"); }
  data = data.join(" ", data);
 
 このdataはOutput枠で認識可(本当です? こんな不思議な仕様・・・?)

[ ]
RE:10324 HmOutputPanel.dllと Output関数No.10325
秀丸担当 さん 21/02/24 16:04
 

Output関数は引数としてUnicodeの文字列として再現する方法はあります。

公開された資料としては存在しないはずです。
(個別にh-tomさんは知っているかもしれないです)

特殊な渡し方は、通常の終端\0のバイト列の文字列として、Unicode1文字(2バイト)
を4バイトに変換して収まっています。
空白区切りや、16進数2桁にしたようなものではないです。
独自のエンコードしたようなもので、Unicode1文字相当のバイト列には\0は入らない
ようになっています。
簡単に言うと、UTF-8の独自仕様版みたいなものです。

[ ]
RE:10325 HmOutputPanel.dllと Output関数No.10326
vscode-life さん 21/02/24 16:33
 
了解です。

ところで、この変換が行われているのは、秀丸エディタ内に含まれるものとしてはHm
OutputPanel だけですか?

それともHmOutputPanelにある「STARTUNIMACRO」といったようなexport関数を備える
一部(あるいはいまんところ1つ?)のdllのみ
このような特殊な変換をするという関数を搭載していますか?

[ ]
RE:10326 HmOutputPanel.dllと Output関数No.10327
秀丸担当 さん 21/02/24 17:06
 

秀丸エディタ内に含まれるものとしては、HmExplorerPane.dllとHmJre.dllも同じに
なります。
他には秀丸メール用のtkinfo.dllもあります。
STARTUNIMACROというのは確かにその通りで、そういう独自のものを備えるという意
味になってしまうので、通常はエクスポートしないようにしてほしいです。

[ ]
RE:10325 HmOutputPanel.dllと Output関数No.10328
vscode-life さん 21/02/24 18:05
 
うーん、最小サンプルと思しきものを実行してみましたが、文字列は再現されません。
単バイトに収まるもん以外は、段順に4バイトに格納するのではなく、何か数値足す
んでしょうか。

秀丸担当さんの返答に基づくと、以下のようなことを想像すると思うのですが、これ
ではうまくいきません。
wchar_tのバイト列がこう →  Outputの引数の際はこう

みたいな最小サンプルで良いのであると助かります。

#include "pch.h"

#include <iostream>
extern "C" __declspec(dllexport) void __cdecl func() {
    using PFNOUTPUT = int(_cdecl*)(HWND hwnd, char *);
    using PFNGETOUTPUTPANELWINDOWHANDLE = HWND(_cdecl*)(HWND hHidemaru);

    PFNOUTPUT pOutputFunc = NULL;
    PFNGETOUTPUTPANELWINDOWHANDLE pOutputGetWindowFunc = NULL;

    using PFNGETCURRENTWINDOWHANDLE = HWND (WINAPI *)();
    PFNGETCURRENTWINDOWHANDLE pGetCurrentWindowHandle = NULL;

    // アウトプットパネルのDLLのポインタを確保
    HMODULE hHmOutputPaneDLL = LoadLibrary(L"HmOutputPane.dll");
    HMODULE hHidemaruExe = LoadLibrary(L"Hidemaru.exe");

    if (hHmOutputPaneDLL && hHidemaruExe) {

        pGetCurrentWindowHandle = (PFNGETCURRENTWINDOWHANDLE)GetProcAddress
(hHidemaruExe, "Hidemaru_GetCurrentWindowHandle");
        pOutputGetWindowFunc = (PFNGETOUTPUTPANELWINDOWHANDLE)GetProcAddress
(hHmOutputPaneDLL, "GetWindowHandle");

        // アウトプットペインのOutput関数の取得
        // アウトプットペイン自体のウィンドウハンドルの取得。
        pOutputFunc = (PFNOUTPUT)GetProcAddress(hHmOutputPaneDLL, "Output");

        // wchar_t char[] = "a&#9835;b"; // "61 00 6B 26 62 00" + null(00);

        // a&#9835;b 単バイトに収まるものは1つ、そうでないものは4バイトに
        unsigned char a[] = { 0x61,   0x6B, 0x26, 0x00, 0x00,   0x62, 0x00 };

        HWND hWnd = pGetCurrentWindowHandle();
        HWND hOutWnd = pOutputGetWindowFunc(hWnd);
        BOOL success = pOutputFunc(hWnd, (char *)a);
    }
}


BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lp
Reserved )
{
    return TRUE;
}


[ ]
RE:10328 HmOutputPanel.dllと Output関数No.10329
vscode-life さん 21/02/24 18:09
 
おや、文字が化けていますね、
https://www.compart.com/en/unicode/U+266B

化けてるところは、
"a(上の二連音符)b"  という文字です。

[ ]
RE:10329 HmOutputPanel.dllと Output関数No.10330
秀丸担当 さん 21/02/24 18:23
 

独自の方法は独自の計算を加えたもので、その方法は公開されていなくて、できたら
使ってほしくないです。
ちなみに実際はUTF-8のように途中に00が入るようなことは無いもので、文字列全体
として最後に00が1つあるだけのものです。

dllfunc用の関数はやはりdllfuncから呼び出されることを想定したもので、DLL側か
ら呼び出すようなものはHidemaru_*のほうを使ってほしいです。
呼びだし規約も_cdeclとWINAPI(=_stdall)で違っていたりします。

[ ]
RE:10324 HmOutputPanel.dllと Output関数No.10331
でるもんたいいじま さん 21/02/24 23:06
 
でるもんた・いいじまです。

> ・そのOutput枠が認識する特殊な渡し方は、でるもんた・いいじまさんが示す
>  「文字列はバイト列である」が各バイトをバイト「値」ではなく「文字」に変換
>し、
>  さらに文字と文字と空白で連結したもの

すみません、ここの部分で誤解させてしまって申し訳ありません。

私が turukame.3:10319 でサンプルコードを挙げた主旨は、「渡されたバイト列をた
だ16進ダンプして返すだけの関数(の入った自作DLL)を作って、その関数にdllfunc
strでUnicode文字列を渡してみてください」です。

例えば、$a = dllfuncstr(#hMyDLL, "StringHexDumpA", "ABC"); とすれば $a に "4
1 42 43 00" のような文字列を受け取れるように仕込んで(最後に00をつけるかどう
かはお好みで)、次にこの関数にUnicode文字列を食わせてやれば、秀丸内部の実装
が具体的に分かるはずです。

あるいは秀丸に文字列を返さずに、呼ばれたDLLの中で MessageBox() か何かで直接
表示してしまってももちろんOKです。

[ ]
RE:10330 HmOutputPanel.dllと Output関数No.10332
vscode-life さん 21/02/25 02:35
 
>
>独自の方法は独自の計算を加えたもので、その方法は公開されていなくて、できた
>ら使ってほしくないです。

お二人とも返答ありがとうございます。

概ね挙動の確認はできました。

通常の挙動としてはdllfunc(wない方)でUNICODEが含まれた文字を渡しても、fallbac
k済み(潰れた後)のバイト列が渡ってきていますが、
STARTUNIMACRO が定義されている時に限り、挙動が変化し、fallback済みではなく、
別の状態へと特殊なエンコードを伴ったバイト列でわたってきてることを確認しまし
た。


うーむ、複数のモジュールに渡っていますから、これを解決するのはなかなかに難し
いところですねぇ。
変換アルゴリズムそのものの具体的コードを公開するのは私も反対ですので
(将来拡張が必要となった際などの縛りが大きすぎる)

やるとすれば、

HGLOBAL WINAPI Hidemaru_UniqueUnincodeEncode(const wchar *str)で受け取って、
そのアルゴリズムで変換したバイト列返を HGLOBALで確保されてるメモリへと返すぐ
らいですかねぇ。

アルゴリズム自体の隠蔽は確保できますし、おそらく元々似たような形で関数化され
ているでしょうから。

[ ]
RE:10332 HmOutputPanel.dllと Output関数No.10333
秀丸担当 さん 21/02/25 08:19
 

一応これらの問題については、ほぼ解決しているというつもりではあります。
枠のDLLや、HmJreについては、既存のdllfuncのままUnicodeを扱えます。
表面上はマクロファイルですが、マクロファイルはUTF-8やUTF-16で記述できます。

DLL作者様におかれましては、dllfuncwでUnicode対応のDLLを作成できます。
DLL側から秀丸エディタの関数呼び出し(Hidemaru_*)は、全てUnicodeだけになってい
ます。

実は変換モジュールにも同じことがあるのですが、変換モジュールは公開されている
仕様はUnicodeだけになっています。

表面的に見えるのはUnicode(wchar)にできるようにしていて、独自との相互変換は既
に内部で行われています。

それで、今回のことについては、OutputWのような関数を追加したとしても、DLL側か
ら呼ぶのは推奨しないです。
DLL側から呼ぶのはHidemaru_*のほうを推奨します。
一応現状でHidemaru_EvalMacroでできるのと、もっとより直接的にしたいということ
であれば、Hidemaru_Logのような新しいものを作るのであればありかも、ということ
でした。

それか、書いていなかったですがトリッキーな解決法としてはHidemaru_CallDllFunc
のような関数を追加して、例えば、
Hidemaru_CallDllFunc(hModule,"OutputW","テキスト");
とかすると解決できそうと思いましたが、どんどん複雑化するのは避けたいと思って
いたとところでした。

[ ]
RE:10333 HmOutputPanel.dllと Output関数No.10334
vscode-life さん 21/02/25 15:48
 
了解です、一旦この要望は取り下げようと思います。
おさがわせしました。

一応自分の方で、少なくとも現在のwchar_tの文字範囲では、Unicode文字を再現する
形で、Output関数へと放り投げることが出来るようになりました。

自分が利用する範囲では、これで十分だと思いますので、当面これでいこうかとおも
います。

[ ]
RE:10334 HmOutputPanel.dllと Output関数No.10346
秀丸担当 さん 21/03/24 16:59
 

V8.98β3で幾つかの関連する修正をしています。
OutputW関数は一応追加していますが、マクロから使う場合はOutput関数でもUnicode
は使えるので、あまり意味は無いです。
一応現状で外部DLLからも呼べてしまうと思いますが、将来的にOutput関数とOutputW
関数はパラメータチェックをするかもしれません。

DLL側から呼ぶ関数として、Hidemaru_DebugInfoというのを追加しています。(Hidem
aru_Logという案がありましたがその代わりです)
debuginfo文で文字列を指定するのと同じ効果で、マクロ側の先頭でdebuginfo 2;と
するかどうかで一括してアウトプット枠を使うかどうかを切り替えできます。

setcomdetachmethodという文を追加して、COMオブジェクトの解放時に呼ばれるメソ
ッドの指定ができます。
DllDetachFunc_After_Hm866のような既定の関数名のようなものは無くて、常に指定
する必要があります。

[ ]
RE:10346 setcomdetachmethodNo.10347
vscode-life さん 21/03/25 23:27
 
>setcomdetachmethodという文を追加して、COMオブジェクトの解放時に呼ばれるメソ
>ッドの指定ができます。

setcomdetachmethod のメソッドの挙動を確認しましたが、
バグっぽい挙動をしているようにも思えます。

- dll側(.net4.8) --- ClassLibrary72.dll ---------------------------
using System;
using System.Runtime.InteropServices;

namespace ClassLibrary72
{
    [Guid("DDD22F31-7105-4232-8B63-7661326C353D")]
    public class Class1
    {
        // 現在は引数無し前提でCOM関数として呼ばれている(がもしも将来引数付
きで呼ばれるようになると、引数無し関数として定義していたものは全く呼ばれなく
なってしまうので、どちらでも
大丈夫なようにデフォルト引数を付けておく)
        public int OnDetachMethod(int status = 0)
        {
            System.Diagnostics.Trace.WriteLine($"終了ステータス{status}\n");

            return 3;
        }
    }
}

- .mac 側 @ releaseobjectはOnDetachMethodを呼ぶ OK ------------------------
---------------
#obj = createobject( currentmacrodirectory + @"\ClassLibrary72.dll", "ClassL
ibrary72.Class1");

setcomdetachmethod #obj, "OnDetachMethod";
releaseobject(#obj);

- .mac 側 A 秀丸終了時に OnDetachMethodが呼ばれてる OK (細かい点はチェック
していない。1回実行した後、マクロを書き換えてcreateobjectをする前に、releas
eobjectを先に書いた場合など---------------------------------------
##obj = createobject( currentmacrodirectory + @"\ClassLibrary72.dll", "Class
Library72.Class1");
keepobject #obj, 2;

setcomdetachmethod #obj, "OnDetachMethod";

- .mac 側 B 秀丸終了時に OnDetachMethodが呼ばれてない(★★★おそらく実装ミ
ス?★★★) ---------------------------------------
##obj = createobject( currentmacrodirectory + @"\ClassLibrary72.dll", "Class
Library72.Class1");
keepobject #obj, 1;

setcomdetachmethod #obj, "OnDetachMethod";


[ ]
RE:10347 setcomdetachmethodNo.10348
秀丸担当 さん 21/03/26 09:08
 

早速のご確認ありがとうございます。
keepobject #obj,1;の場合は、確かにsetcomdetachmethodのメソッドは呼ばれないこ
とになってしまいます。
keepobject #obj,1;はcreateobjectしたことも忘れて放置するための呼び方で、呼ば
れるように修正するとしたら、keepobject #obj,2;との差異が全くないことになりま
す。
というか、そもそも1と2を使い分ける必要はあまりなく、1相当で忘れたい場合は単
に#objを使わないようにするだけでいいので、どちらも2相当に仕様変更してしまっ
てもいいかもしれません。
1でも2相当となるように仕様変更してしまおうと思います。

[ ]