如何将 Variant(包含数组)转换为数组,并将其作为参数传递?

maf*_*oft 2 arrays delphi variant

我需要调用一个需要 的函数array of Integer,但我的值位于一个类型为 的变量中Variant,其中包含数组。

我真的必须在循环中复制值吗?我找不到更好的方法。

相同的变体也可以保存单个Integer而不是数组,因此我创建了一个允许两者都使用的辅助函数(使用 进行检查VarIsArray)。它有效,但它很长而且不好:)

type
  TIntegerArray = array of Integer;

function VarToArrayInt(const V: Variant): TIntegerArray;
var
  I: Integer;
begin
  if VarIsArray(V) then begin
    SetLength(Result, VarArrayHighBound(V, 1) + 1);
    for I:= 0 to High(Result) do Result[I]:= V[I];
  end else begin
    SetLength(Result, 1);
    Result[0]:= V;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

我正在使用 Delphi 10.2.2 并且无法更改要调用的函数,如下所示:

function Work(Otherparameters; const AParams: array of Integer): Boolean;
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

如果函数将 anarray of Integer作为单独的类型,例如:

type
  TIntegerArray = array of Integer;

function DoIt(const Values: TIntegerArray): ReturnType;
Run Code Online (Sandbox Code Playgroud)

然后该函数将动态数组作为输入。您可以将Variant持有数组分配/传递给动态数组变量/参数。编译器足够聪明,可以调用 RTL 的VarToDynArray()函数来分配一个新的动态数组,该数组具有Variant的数组元素的副本。Variant如果不复制数组数据,就无法将持有数组传递给动态数组。

但是,如果函数array of Integer直接在其参数列表中采用 ,例如:

function DoIt(const Values: array of Integer): ReturnType;
Run Code Online (Sandbox Code Playgroud)

然后它需要一个Open Array作为输入:

可以通过显式传递两个参数来调用具有开放数组参数的 Delphi 函数:

  • 指向数组第一个元素的指针
  • 一个计数,即最后一个索引的值(即数组元素的大小/数量,减一)"

您不能将 a Variant(无论它是否包含数组)直接传递给 Open Array 参数。编译器不够聪明,无法提取数组指针和元素计数并将它们传递给 Open Array 参数。但是,您可以使用一些类型转换技巧手动完成,例如:

function DoIt(const Values: array of Integer): ReturnType;

...

type
  TOpenArrayFunc = function(const Values: PInteger; ValuesHigh: Integer): ReturnType;

var
  V: Variant;
  Count: Integer;
  P: PInteger;
begin
  ...
  V := ...;
  Count := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
  P := VarArrayLock(V);
  try
    TOpenArrayFunc(@DoIt)(P, Count-1);
  finally
    VarArrayUnlock(V);
  end;
  ...
end;
Run Code Online (Sandbox Code Playgroud)

这将Variant的数组直接传递给函数,而根本不制作数组元素的任何副本。