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

■秀丸エディタ64bit版

-----------.mac側
#com = createobject( currentmacrodirectory + @"\ClassLibrary15.dll", "ClassL
ibrary15.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版の方に、(32
bitのソースに引っ張られる形で)
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の理由のパラメータも追加しています。

[ ]