|
毎度お世話になっております。
さて、.Net Framework 4系のCOMを浮動小数点数モードで使用することについてです
が、倍精度浮動小数点数(.NetのSystem.Double型)を
COM側=>秀丸マクロ側の転送は正常に行えるのですが、秀丸マクロ側=>COM側の転送で
は値がおかしくなってしまいます。
具体的には、秀丸マクロ側でsetpropnum文でプロパティを呼び出したりcallmethod文
などの引数に値を指定してメソッドを呼び出すと、
COM側で受け取った値が
1. 小数点以下が切り詰められる。
2. 元の値の範囲が符号付32bit整数の範囲を超えているときには0x80000000に相
当する値に化ける。
となってしまっています。
検証コードと実行結果は以下の通りです。
// ------------------------------------------------ FloatCom.dll -----------
-------------------------------------
using System.Runtime.InteropServices ;
using System.Globalization ;
using System.Collections.Generic ;
using System.Collections.ObjectModel ;
using System ;
namespace FloatCom {
internal static class Converter {
public static readonly IFormatProvider FormatProvider
= (IFormatProvider) ( CultureInfo.InvariantCulture )
;
public static Double FromInt32( Int32 @value ) {
return ( (IConvertible) @value ).ToDouble( FormatProvider ) ;
}
public static Double FromInt64( Int64 @value ) {
return ( (IConvertible) @value ).ToDouble( FormatProvider ) ;
}
public static String ToString( Double @value ) {
return @value.ToString( @"E16" , FormatProvider ) ;
}
}
internal static class CommonData {
public static readonly Double Int32MinValue = Converter.FromInt32( I
nt32.MinValue ) ;
public static readonly Double Int32MaxValue = Converter.FromInt32( I
nt32.MaxValue ) ;
public static readonly Double Int64MinValue = Converter.FromInt64( I
nt64.MinValue ) ;
public static readonly Double Int64MaxValue = Converter.FromInt64( I
nt64.MaxValue ) ;
}
internal class SampleItem {
public readonly String Name = default( String ) ;
public readonly Double Value = default( Double ) ;
public SampleItem( String name , Double @value ) {
this.Name = name ?? String.Empty ;
this.Value = @value ;
}
public String Format() {
return Converter.ToString( this.Value ) ;
}
}
internal static class Sample {
private static readonly SampleItem[] items = default( SampleItem[] ) ;
public static readonly ReadOnlyCollection< SampleItem > Items
= default( ReadOnlyCollection< SampleItem > )
;
static Sample() {
items = new SampleItem[] {
new SampleItem( @"NaN" , Double.NaN
) ,
new SampleItem( @"NegativeInfinity" , Double.NegativeInfin
ity ) ,
new SampleItem( @"MinValue" , Double.MinValue
) ,
new SampleItem( @"HalfMinValue" , Double.MinValue / 2.
0D ) ,
new SampleItem( @"QuarterMinValue" , Double.MinValue / 4.
0D ) ,
new SampleItem( @"UnderInt64MinValue" , CommonData.Int64MinV
alue * 2.0D ) ,
new SampleItem( @"Int64MinValue" , CommonData.Int64MinV
alue ) ,
new SampleItem( @"OverInt64MinValue" , CommonData.Int64MinV
alue / 2.0D ) ,
new SampleItem( @"UnderInt32MinValue" , CommonData.Int32MinV
alue * 2.0D ) ,
new SampleItem( @"Int32MinValue" , CommonData.Int32MinV
alue ) ,
new SampleItem( @"OverInt32MinValue" , CommonData.Int32MinV
alue / 2.0D ) ,
new SampleItem( @"NegativeTwo" , -2.0D
) ,
new SampleItem( @"NegativeOne" , -1.0D
) ,
new SampleItem( @"NegativeHalf" , -0.5D
) ,
new SampleItem( @"NegativeEpsilon" , - Double.Epsilon
) ,
new SampleItem( @"Zero" , 0.0D
) ,
new SampleItem( @"PositiveEpsilon" , Double.Epsilon
) ,
new SampleItem( @"PositiveHalf" , 0.5D
) ,
new SampleItem( @"PositiveOne" , 1.0D
) ,
new SampleItem( @"PositiveTwo" , 2.0D
) ,
new SampleItem( @"UnderInt32MaxValue" , CommonData.Int32MaxV
alue / 2.0D ) ,
new SampleItem( @"Int32MaxValue" , CommonData.Int32MaxV
alue ) ,
new SampleItem( @"OverInt32MaxValue" , CommonData.Int32MaxV
alue * 2.0D ) ,
new SampleItem( @"UnderInt64MaxValue" , CommonData.Int64MaxV
alue / 2.0D ) ,
new SampleItem( @"Int64MaxValue" , CommonData.Int64MaxV
alue ) ,
new SampleItem( @"OverInt64MaxValue" , CommonData.Int64MaxV
alue * 2.0D ) ,
new SampleItem( @"QuarterMaxValue" , Double.MaxValue / 4.
0D ) ,
new SampleItem( @"HalfMaxValue" , Double.MaxValue / 2.
0D ) ,
new SampleItem( @"MaxValue" , Double.MaxValue
) ,
new SampleItem( @"PositiveInfinity" , Double.PositiveInfin
ity ) ,
} ;
Items = new ReadOnlyCollection< SampleItem >( (IList< SampleItem
>) items ) ;
}
}
[ ComVisible( true ) ]
[ GuidAttribute( @"1c57955c-dfb0-4fe6-802b-49513fe8bde6" ) ]
[ InterfaceType( ComInterfaceType.InterfaceIsIUnknown ) ]
public interface ITest {
Int32 Count { get ; }
Int32 Index { get ; set ; }
String Name { get ; }
Double Value { get ; } // COM内の値をマクロに渡す。
Double GetValue() ; // Valueプロパティのメソッド版。
Double Memory { get ; set ; } // COM内の変数をマクロから読み
書きする。
Double GetMemory() ; // Memoryプロパティ(get)のメソ
ッド版。
void SetMemory( Double @value ) ; // Memoryプロパティ(set)のメソ
ッド版。
void ClearMemory() ;
Double Echo( Double @value ) ; // マクロから受け取った値をオウ
ム返しする。
String Format() ; // COM内の値を文字列に変換する。
String FormatFrom( Double @value ) ; // マクロから受け取った値を文字
列に変換する。
}
[ ComVisible( true ) ]
[ GuidAttribute( @"30080a58-e01f-426a-9743-e923e25ba28f" ) ]
[ InterfaceType( ComInterfaceType.InterfaceIsIDispatch ) ]
public interface ITestEvent {}
[ ComVisible( true ) ]
[ GuidAttribute( @"d71988aa-6e1a-442b-8046-5c9c0295cb01" ) ]
[ ClassInterface( ClassInterfaceType.AutoDual ) ]
[ ComSourceInterfaces( typeof( ITestEvent ) ) ]
public class Test : ITest {
public Int32 Count { get { return Sample.Items.Count ; } }
private Int32 index = -1 ;
public Int32 Index { get { return this.index ; } set { this.index =
value ; } }
public String Name { get { return Sample.Items[ this.Index ].Name ; } }
public Double Value { get { return Sample.Items[ this.Index ].Value
; } }
public Double GetValue() { return this.Value ; }
private Double memory = default( Double ) ;
public Double Memory { get { return this.memory ; } set { this.memor
y = value ; } }
public Double GetMemory() { return this.Memory ; }
public void SetMemory( Double @value ) { this.Memory = @value ; }
public void ClearMemory() { this.Memory = default( Double ) ; }
public Double Echo( Double @value ) { return @value ; }
public String Format() { return Sample.Items[ this.Index ].Format() ; }
public String FormatFrom( Double @value ) { return Converter.ToStrin
g( @value ) ; }
}
}
// ------------------------------------------------ FloatCom.mac -----------
-------------------------------------
debuginfo 2 ;
#test = createobject( currentmacrodirectory + @"\FloatCom.dll" , @"FloatCom.
Test" ) ;
#count = getpropnum( #test , @"Count" ) ;
#index = 0 ;
while ( #index < #count ) {
setpropnum #test , @"Index" , #index ;
call WriteLine @"[" + getpropstr( #test , @"Name" ) + @"]" ;
setfloatmode 1 ;
// COM内の値をマクロ側に受け取る。
#value = getpropnum( #test , @"Value" ) ;
call WriteNumber @"Value" , #value ;
// メソッドを使用してCOM内の値をマクロ側に受け取る。
call WriteNumber @"GetValue" , callmethod_returnnum( #test , @"G
etValue" ) ;
// 値をマクロ側からCOM内の変数に送る。
setpropnum #test , @"Memory" , #value ;
// COM内の変数に送った値をマクロ側に受け取る。
call WriteNumber @"Memory" , getpropnum( #test , @"Memory" ) ;
// 値をマクロ側からCOM内の変数に送る(メソッド使用)。
callmethod #test , @"SetMemory" , #value ;
// COM内の変数に送った値をマクロ側に受け取る(メソッド使用)。
call WriteNumber @"GetMemory" , callmethod_returnnum( #test , @"
GetMemory" ) ;
callmethod #test , @"ClearMemory" ;
// 値をマクロ側とCOM側との間で往復させる。
call WriteNumber @"Echo" , callmethod_returnnum( #test , @"Echo"
, #value ) ;
// COM内の元の値をCOM側で文字列に変換する。
call WriteString @"Format" , callmethod_returnstr( #test , @"For
mat" ) ;
// 値をマクロ側からCOM側に送ってCOM側で文字列に変換する。
call WriteString @"FormatFrom" , callmethod_returnstr( #test , @
"FormatFrom" , #value ) ;
#value = 0 ;
setfloatmode 0 ;
call WriteLine @"" ;
#index = #index + 1 ;
}
releaseobject #test ;
endmacro ;
WriteNumber :
call WriteString $$1 , str( ##2 ) ;
return ;
WriteString :
call WriteLine $$1 + @" = " + $$2 ;
return ;
WriteLine :
debuginfo $$1 + "\U0000000A" ;
return ;
// ------------------------------------------------ 実行結果 ---------------
---------------------------------
[NaN]
Value = -1.#IND
GetValue = -1.#IND
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = NaN
FormatFrom = -2.1474836480000000E+009
[NegativeInfinity]
Value = -1.#INF
GetValue = -1.#INF
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -Infinity
FormatFrom = -2.1474836480000000E+009
[MinValue]
Value = -1.79769313486232E+308
GetValue = -1.79769313486232E+308
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -1.7976931348623157E+308
FormatFrom = -2.1474836480000000E+009
[HalfMinValue]
Value = -8.98846567431158E+307
GetValue = -8.98846567431158E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -8.9884656743115785E+307
FormatFrom = -2.1474836480000000E+009
[QuarterMinValue]
Value = -4.49423283715579E+307
GetValue = -4.49423283715579E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -4.4942328371557893E+307
FormatFrom = -2.1474836480000000E+009
[UnderInt64MinValue]
Value = -1.84467440737096E+019
GetValue = -1.84467440737096E+019
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -1.8446744073709552E+019
FormatFrom = -2.1474836480000000E+009
[Int64MinValue]
Value = -9.22337203685478E+018
GetValue = -9.22337203685478E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -9.2233720368547758E+018
FormatFrom = -2.1474836480000000E+009
[OverInt64MinValue]
Value = -4.61168601842739E+018
GetValue = -4.61168601842739E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -4.6116860184273879E+018
FormatFrom = -2.1474836480000000E+009
[UnderInt32MinValue]
Value = -4294967296
GetValue = -4294967296
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -4.2949672960000000E+009
FormatFrom = -2.1474836480000000E+009
[Int32MinValue]
Value = -2147483648
GetValue = -2147483648
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -2.1474836480000000E+009
FormatFrom = -2.1474836480000000E+009
[OverInt32MinValue]
Value = -1073741824
GetValue = -1073741824
Memory = -1073741824
GetMemory = -1073741824
Echo = -1073741824
Format = -1.0737418240000000E+009
FormatFrom = -1.0737418240000000E+009
[NegativeTwo]
Value = -2
GetValue = -2
Memory = -2
GetMemory = -2
Echo = -2
Format = -2.0000000000000000E+000
FormatFrom = -2.0000000000000000E+000
[NegativeOne]
Value = -1
GetValue = -1
Memory = -1
GetMemory = -1
Echo = -1
Format = -1.0000000000000000E+000
FormatFrom = -1.0000000000000000E+000
[NegativeHalf]
Value = -0.5
GetValue = -0.5
Memory = 0
GetMemory = 0
Echo = 0
Format = -5.0000000000000000E-001
FormatFrom = 0.0000000000000000E+000
[NegativeEpsilon]
Value = -4.94065645841247E-324
GetValue = -4.94065645841247E-324
Memory = 0
GetMemory = 0
Echo = 0
Format = -4.9406564584124654E-324
FormatFrom = 0.0000000000000000E+000
[Zero]
Value = 0
GetValue = 0
Memory = 0
GetMemory = 0
Echo = 0
Format = 0.0000000000000000E+000
FormatFrom = 0.0000000000000000E+000
[PositiveEpsilon]
Value = 4.94065645841247E-324
GetValue = 4.94065645841247E-324
Memory = 0
GetMemory = 0
Echo = 0
Format = 4.9406564584124654E-324
FormatFrom = 0.0000000000000000E+000
[PositiveHalf]
Value = 0.5
GetValue = 0.5
Memory = 0
GetMemory = 0
Echo = 0
Format = 5.0000000000000000E-001
FormatFrom = 0.0000000000000000E+000
[PositiveOne]
Value = 1
GetValue = 1
Memory = 1
GetMemory = 1
Echo = 1
Format = 1.0000000000000000E+000
FormatFrom = 1.0000000000000000E+000
[PositiveTwo]
Value = 2
GetValue = 2
Memory = 2
GetMemory = 2
Echo = 2
Format = 2.0000000000000000E+000
FormatFrom = 2.0000000000000000E+000
[UnderInt32MaxValue]
Value = 1073741823.5
GetValue = 1073741823.5
Memory = 1073741823
GetMemory = 1073741823
Echo = 1073741823
Format = 1.0737418235000000E+009
FormatFrom = 1.0737418230000000E+009
[Int32MaxValue]
Value = 2147483647
GetValue = 2147483647
Memory = 2147483647
GetMemory = 2147483647
Echo = 2147483647
Format = 2.1474836470000000E+009
FormatFrom = 2.1474836470000000E+009
[OverInt32MaxValue]
Value = 4294967294
GetValue = 4294967294
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 4.2949672940000000E+009
FormatFrom = -2.1474836480000000E+009
[UnderInt64MaxValue]
Value = 4.61168601842739E+018
GetValue = 4.61168601842739E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 4.6116860184273879E+018
FormatFrom = -2.1474836480000000E+009
[Int64MaxValue]
Value = 9.22337203685478E+018
GetValue = 9.22337203685478E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 9.2233720368547758E+018
FormatFrom = -2.1474836480000000E+009
[OverInt64MaxValue]
Value = 1.84467440737096E+019
GetValue = 1.84467440737096E+019
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 1.8446744073709552E+019
FormatFrom = -2.1474836480000000E+009
[QuarterMaxValue]
Value = 4.49423283715579E+307
GetValue = 4.49423283715579E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 4.4942328371557893E+307
FormatFrom = -2.1474836480000000E+009
[HalfMaxValue]
Value = 8.98846567431158E+307
GetValue = 8.98846567431158E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 8.9884656743115785E+307
FormatFrom = -2.1474836480000000E+009
[MaxValue]
Value = 1.79769313486232E+308
GetValue = 1.79769313486232E+308
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 1.7976931348623157E+308
FormatFrom = -2.1474836480000000E+009
[PositiveInfinity]
Value = 1.#INF
GetValue = 1.#INF
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = Infinity
FormatFrom = -2.1474836480000000E+009
|
|