我正在尝试将字节数组从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
我可以让服务器接受脚本传递的油变量,但数据似乎乱码,下面显示了我的示例服务器代码,该代码基于此处的Stackoverflow问题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在其注释中指出的那样)。要在您的方法中处理这样的数组,您必须声明:
您可以为此编写帮助程序:
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个实例保存在内存中-作为变体数组和字节数组。将其应用于用例时,请以它为指导。