[ 新規に投稿する ]

秀丸64bitのcom関連でmemberへの数値型の引数と返り値のビッNo.10388
こみやんま さん 21/05/11 01:28 [ コメントを投稿する ]
  以前の投稿では、秀丸のCOM関連独自の仕様だと思いスルーしたのですが、
ちょっと仕様とは思い難く、「仕様」があまりに変、もしくは「実装」にキャストバグ、があるとしか思えないので、
投稿します。

■秀丸エディタ64bit版

-----------.mac側
#com = createobject( currentmacrodirectory + @"\ClassLibrary15.dll", "ClassLibrary15.Class1");

#r = member(#com, "abc", 30000000000000);
message(str(#r));
releaseobject(#com);


-----------.c#側 (ClassLibrary15.dllとしてコンパイル。COM公開のこと、.net4でも.net5でも良いが64bit状態で走るように)

using System;
using System.Runtime.InteropServices;

namespace ClassLibrary15
{
    [Guid("6F519100-D5FF-498E-B2ED-5C2716761A16")]
    public class Class1
    {
        public long abc(long a)
        {
            System.Diagnostics.Trace.WriteLine(a.ToString());
            return 30000000000000;
        }
    }
}


// この状態で、aには「-346562560」が格納されます。(30000000000000 を intでキャストした[4バイト分だけで判断した]数値)
// (long型と明示はせず、なんでもこいのobject型にした際は、64bit版であるにもかかわらずInt32型としてわたってきます)

一方で、30000000000000 は明らかにInt32.maxValueを超えていますが、
こちらの方は問題なく秀丸のマクロ変数が受け止めています。
(※ message(str(#r)) のダイアログボックスは30000000000000を表示する)

ということは、「秀丸エディタ64bit版」は「COM関連」では、「引数が数値型」の時、「32bitビットにキャストして」引数として渡しているが、
「返り値を受け取るときには64bit幅まで」受け取る、というよくわからないチグハグな状態になっているようです。

これはおそらく意図した仕様ではなく、おそらく、秀丸エディタ64bit版の方に、(32bitのソースに引っ張られる形で)
intptr_tでキャストすべきところ、intでキャストしているところがあるのではないかと思います。

一度ご確認のほどよろしくお願いします。

[ ]
RE:10388 秀丸64bitのcom関連でmemberへの数値型の引数と返り値No.10391
秀丸担当 さん 21/05/11 09:56 [ コメントを投稿する ]
 
調べてみたところ、COMの数値パラメータの受け渡しは、確かに64bit版秀丸エディタであっても、32bitにしてありました。
V8.03のときにそういう変更がありました。

まず32bit/64bit版に関わらずマクロの動作は同じにしたいという目標から、本当は数値は全て32bitにしたいところなのですが、数値変数にポインタやハンドルを格納する可能性から、実際は64bit版では64bit値を格納できるようにしています。

COMメンバへ数値パラメータを渡すときは、V8.02以前では64bit版では64bit値にしていたのですが、V8.03以降では32bit値の固定にしています。
例えば、以下のようなマクロで、メモ帳を最小化で起動するとき、最後のパラメータが64bit値だと失敗していました。
#obj = createobject("Shell.Application");
member #obj,"ShellExecute","notepad.exe","","","",7;
32bit値の固定にして、32bit/64bit版でも同じマクロで実行できるようになっています。
一応現状の仕様ということでヘルプのどこかに書いておこうと思います。

パラメータ指定でビット幅固定にしないといけないのは、秀丸エディタの呼び出し方がIDispatchのみなのに起因している気がします。
この仕組みのままなんとかするとしたら、allowobjparamで明示的に数値のビット幅を指定できればなんとかできるとは思います。
[ ]
RE:10391 秀丸64bitのcom関連でmemberへの数値型の引数と返りNo.10393
こみやんま さん 21/05/11 14:53 [ コメントを投稿する ]
  呼ぶ側が allowobjparam の指定をもって、64bitを指定するというのはちょっと違和感を感じます。

そのCOMオブジェクトがx64まで整数を意識して処理できるように制作しているかどうかは、利用する側ではなく、dll(COM側)が決めてプログラムするからです。

COMではなくloaddllの方の dllfuncにおいて、浮動小数秀丸用に 
extern "C" void FLOATMACRO() {} といった切り替え定義方法があるのと類似の考え方で、

対象のCOMインスタンスに、メソッドとして、BOOL X64MACRO()が定義されて、かつ非ゼロ値が返ってくれば、対象のCOMインスタンスは整数の引数渡しについて、64bit幅そのままで渡す、などのほうが良いように思います。

using System;
using System.Runtime.InteropServices;

namespace ClassLibrary15
{
    [Guid("6F519100-D5FF-498E-B2ED-5C2716761A16")]
    public class Class1
    {
        public long abc(long a)
        {
            System.Diagnostics.Trace.WriteLine(a.ToString());
            return 30000000000000;
        }

        // このメソッドを持つCOMオブジェクトは、引数渡しにおいて
        // 秀丸64bit版なら64bit引数としてそのままのビット幅を受け取る。
        public bool X64MACRO() {
            return true;
        }
    }
}


[ ]
RE:10393 秀丸64bitのcom関連でmemberへの数値型の引数と返りNo.10394
秀丸担当 さん 21/05/11 17:24 [ コメントを投稿する ]
 
本来であればタイプライブラリとして提供されていて、呼ぶ側の秀丸エディタもタイプライブラリを調べるというのがあるべきところなのだと思いますが、だいぶん複雑です。
X64MACRO()というメソッドがあってそれで判別するという方法は結構マニアックだとは思いますが、どちらかというとX64MACRO()で判別できたりしたら、そちらのほうがやりやすいです。
そういう方法でできないかやってみます。
[ ]
RE:10393 秀丸64bitのcom関連でmemberへの数値型の引数と返りNo.10396
秀丸担当 さん 21/05/17 09:48 [ コメントを投稿する ]
 
V8.98β8で、X64MACROの方式でやってみています。
いまのところヘルプには書いていないです。

あと、keepdll文と、setcomdetachmethodの理由のパラメータも追加しています。
[ ]

[ 新規に投稿する ]