【发布时间】:2021-09-12 20:51:09
【问题描述】:
我正在尝试将 OleVariant 数组复制到我自己的结构中。我收到了来自外部 COM 调用的 OleVariant。
大小为 1000 x 500 个元素(不知道是不是和这个结构定义一样:array of array of OleVariant)。
目前,我正在尝试实现以下目标:
result := Copy(Source, Amount)
但是OleVariant 结构妨碍了我。
如果我使用“经典”循环,它可以工作,但速度很慢(非常慢)。
aResult 当前定义为TData = array of array of string;
procedure CopyResult(aResultCount: Integer; var aResult: TData; aSource: Variant);
var
i, j: Integer;
bVariantConversion: boolean;
begin
SetLength(aResult, aResultCount, VarArrayHighBound(aSource[0], 1));
bVariantConversion := NullStrictConvert; // settings to manage how string conversion for Variant is handled.
NullStrictConvert := False;
try
for i := VarArrayLowBound(aSource, 1) to VarArrayHighBound(aSource, 1) do
begin
for j := VarArrayLowBound(aSource[i], 1) to pred(VarArrayHighBound(aSource[i], 1)) do
begin
//nearly every execution pause is somewhere in this String Conversion or Array Function.
aResult[i][j] := aSource[i][j]; //implicit conversion to string ...
end;
end;
finally
NullStrictConvert := bVariantConversion;
end;
end;
正如@Remy Lebau 提到的,检查 Vararray[x][y] 访问的边界是我的源代码消耗时间的例程。我试图通过直接访问 OleVariantArray 元素来消除这种访问。
后果... 试图确定我的结构,我想我找到了根。
tmyVarType := VarType(aSource); //8204 => Array(VT_ARRAY = 0x2000 = 8192) + variant(VT_VARIANT = 0x000C = 12)
tmyVarType := VarType(aSource[0]); //8204
tmyVarType := VarType(aSource[0][0]); //3 VT_I4 = 0x0003 = 3 is integer and this is correctly changin for the fields.
所以我尝试在没有内置函数的情况下访问源代码以避免边界检查。
【问题讨论】:
-
加快代码速度的一种方法是去掉循环中所有重复的
VarArray(Low|High)Bound()调用。您知道数组具有固定大小,因此在进入循环之前计算大小并将其缓存到局部变量中。看起来你已经有了aResultCount的外部尺寸,所以你真正需要的是内部尺寸,它是VarArrayHighBound(aSource[0], 1) - VarArrayLowBound(aSource[0], 1) + 1(不是VarArrayHighBound(aSource[0], 1)本身)。 -
至于数据的实际复制,除非你知道
Variant数组在每个元素中保存的数据类型,否则使用VarArrayLock()并不是很有用。是VT_BSTR(OLE 字符串数组)、VT_VARIANT(OLE 变体数组)等吗?您可能无法避免单独复制每个元素,但至少VarArrayLock()将允许您使用指针算法更快地访问元素,而不是使用委托给VarArrayGet()并进行边界检查的[]运算符.VarType()为外部数组aSource和每个内部数组aSource[i]返回什么? -
如果您能告诉我们
VarType(aSource)的结果会有所帮助。它决定了您可以通过VarArrayLock访问哪些数据。 -
@StijnSanders 我想我现在了解结构。我正在记录我在问题中的进展。 tmyVarType := VarType(aSource); tmyVarType := VarType(aSource[0]); tmyVarType := VarType(aSource[0][0]);前 2 个给我一个 8204,它是一个变体数组,最后一个是 3 个整数。但它会根据我调用 VarType 的每个单元格而相应地发生变化。我想我现在可以看到解决方案了。
-
@RemyLebeau 是的,每次我在循环中的某个地方点击暂停 iam 以进行绑定检查。我尽量避免使用“std”功能并写我的。问题将被多次编辑......随着我的进步。