如何解释从 VBscript 传递到 Delphi COM 服务器应用程序的数组
How to interpret arrays passed from VBscript to a Delphi COM server App
我正在尝试将字节数组从 VBscript 传递到我的 windows Delphi 应用程序,但似乎找不到正确的语法来解释传递的数据。
要求非常简单,如下面的 VBscript 代码片段所示
Dim inst,arr(5)
Sub Main
set inst=instruments.Find("EP1")
arr(0) = 0
arr(1) = 1
arr(2) = 2
arr(3) = 3
arr(4) = 4
inst.writebytes arr,5
end Sub
我可以让服务器接受脚本传递的 olevariant 但数据似乎是乱码,我的示例服务器代码如下所示,它基于此处的 Whosebug 问题 How to use variant arrays in Delphi
procedure TInstrument.WriteBytes(Data: OleVariant; Length: Integer);
var i,n:integer; Pdat:Pbyte; Adata:PvarArray;
begin
if VarIsArray(data) then
begin
n:=TVarData(Data).VArray^.Bounds[0].ElementCount;
Adata:= VarArrayLock(Data);
Getmem(Pdat,length);
try
for i:=0 to length-1 do
Pdat[i]:=integerArray(Adata.data^)[i];
Finstrument.WriteBytes(Pdat,Length);
finally
freemem(Pdat)
end;
end;
end;
所以我的想法是接受脚本传递的整数,将其转换为本地数据表示形式(字节数组),然后将其传递给我的函数以使用数据。
我尝试了几种不同的数据类型和方法,试图从变体中获取一些无误的数据,但都无济于事。
从传递的变量中提取数组数据的正确方法是什么?
此外,TVarData(Data).VArray^.Bounds[0].ElementCount 的值为零,为什么会这样?
在 VBScript 中创建的数组是
- 零基础
- 未打字
- 以上限声明(不是您假设的大小;声明为
Dim arr(5)
的数组大小为 6)
- 在其中包含维度信息(因此您不需要将其与数组一起传递)
在 COM 中使用时,它们作为 varVariant
类型的变体数组传递(正如 Ondrej Kelle 在他的评论中指出的那样)。要在您的方法中处理这样的数组,您必须断言:
- 该值为一维数组
- 每个元素都可以转为byte
您可以为此编写辅助例程:
function ToBytes(const Data: Variant): TBytes;
var
Index, LowBound, HighBound: Integer;
ArrayData: Pointer;
begin
if not VarIsArray(Data) then
raise EArgumentException.Create('Variant array expected.');
if VarArrayDimCount(Data) <> 1 then
raise EArgumentException.Create('Single dimensional variant array expected.');
LowBound := VarArrayLowBound(Data, 1);
HighBound := VarArrayHighBound(Data, 1);
SetLength(Result, HighBound - LowBound + 1);
if TVarData(Data).VType = varArray or varByte then
begin
ArrayData := VarArrayLock(Data);
try
Move(ArrayData^, Result[0], Length(Result));
finally
VarArrayUnlock(Data);
end;
end
else
begin
for Index := LowBound to HighBound do
Result[Index - LowBound] := Data[Index];
end;
end;
for
例程中的循环在处理大型数组时会非常慢,因此针对使用 Move
将字节复制到结果的特殊情况(可变字节数组)进行了优化。但 VBScript 数组永远不会发生这种情况。您可以考虑使用 VB.Net 或 PowerShell。
使用这样的例程有一个缺点,即在内存中保留数组的 2 个实例 - 作为变体数组和字节数组。将其应用于您的用例时,将其用作指南。
我正在尝试将字节数组从 VBscript 传递到我的 windows Delphi 应用程序,但似乎找不到正确的语法来解释传递的数据。
要求非常简单,如下面的 VBscript 代码片段所示
Dim inst,arr(5)
Sub Main
set inst=instruments.Find("EP1")
arr(0) = 0
arr(1) = 1
arr(2) = 2
arr(3) = 3
arr(4) = 4
inst.writebytes arr,5
end Sub
我可以让服务器接受脚本传递的 olevariant 但数据似乎是乱码,我的示例服务器代码如下所示,它基于此处的 Whosebug 问题 How to use variant arrays in Delphi
procedure TInstrument.WriteBytes(Data: OleVariant; Length: Integer);
var i,n:integer; Pdat:Pbyte; Adata:PvarArray;
begin
if VarIsArray(data) then
begin
n:=TVarData(Data).VArray^.Bounds[0].ElementCount;
Adata:= VarArrayLock(Data);
Getmem(Pdat,length);
try
for i:=0 to length-1 do
Pdat[i]:=integerArray(Adata.data^)[i];
Finstrument.WriteBytes(Pdat,Length);
finally
freemem(Pdat)
end;
end;
end;
所以我的想法是接受脚本传递的整数,将其转换为本地数据表示形式(字节数组),然后将其传递给我的函数以使用数据。
我尝试了几种不同的数据类型和方法,试图从变体中获取一些无误的数据,但都无济于事。
从传递的变量中提取数组数据的正确方法是什么?
此外,TVarData(Data).VArray^.Bounds[0].ElementCount 的值为零,为什么会这样?
在 VBScript 中创建的数组是
- 零基础
- 未打字
- 以上限声明(不是您假设的大小;声明为
Dim arr(5)
的数组大小为 6) - 在其中包含维度信息(因此您不需要将其与数组一起传递)
在 COM 中使用时,它们作为 varVariant
类型的变体数组传递(正如 Ondrej Kelle 在他的评论中指出的那样)。要在您的方法中处理这样的数组,您必须断言:
- 该值为一维数组
- 每个元素都可以转为byte
您可以为此编写辅助例程:
function ToBytes(const Data: Variant): TBytes;
var
Index, LowBound, HighBound: Integer;
ArrayData: Pointer;
begin
if not VarIsArray(Data) then
raise EArgumentException.Create('Variant array expected.');
if VarArrayDimCount(Data) <> 1 then
raise EArgumentException.Create('Single dimensional variant array expected.');
LowBound := VarArrayLowBound(Data, 1);
HighBound := VarArrayHighBound(Data, 1);
SetLength(Result, HighBound - LowBound + 1);
if TVarData(Data).VType = varArray or varByte then
begin
ArrayData := VarArrayLock(Data);
try
Move(ArrayData^, Result[0], Length(Result));
finally
VarArrayUnlock(Data);
end;
end
else
begin
for Index := LowBound to HighBound do
Result[Index - LowBound] := Data[Index];
end;
end;
for
例程中的循环在处理大型数组时会非常慢,因此针对使用 Move
将字节复制到结果的特殊情况(可变字节数组)进行了优化。但 VBScript 数组永远不会发生这种情况。您可以考虑使用 VB.Net 或 PowerShell。
使用这样的例程有一个缺点,即在内存中保留数组的 2 个实例 - 作为变体数组和字节数组。将其应用于您的用例时,将其用作指南。