Es gibt zwei Fehler hier.
Zuerst in Variants.DynArrayVariantBounds
. Wenn das dynamische Array nil
ist, wird fälschlicherweise ein Low/High-Paar von (0, 0)
zurückgegeben. Es sollte (0, -1)
zurückgeben. Dieser Fehler wurde in den neuesten Versionen von Delphi behoben. Das verursacht V := sa
, um ein Variantenarray mit einem einzelnen leeren Element zurückzugeben. Der zweite Fehler betrifft die andere Richtung, sa := V
. Dieser Fehler ist immer noch in den neuesten Versionen von Delphi vorhanden. Dieser Fehler ist in Variants.DynArrayFromVariant
. Es gibt eine repeat/until
Schleife, die über das Array mit der Eingabevariante läuft und das dynamische Ausgabe-Array auffüllt. Wenn das Eingabe-Varianten-Array leer ist, sollte es nicht in die repeat/until
-Schleife eintreten. Der Code tut dies jedoch fälschlicherweise und versucht, ein Element des Varianten-Arrays mit zu lesen. Da das Array leer ist, verursacht das einen Laufzeitfehler. Ich habe dies gemeldet: QC#109445.
Hier ist ein sehr einfaches Stück Code, das die Fehler behebt. Beachten Sie, dass ich nur den Fall betrachte, in dem die Arrays eindimensional sind. Wenn Sie höherdimensionale Arrays unterstützen müssen, können Sie diesen Ansatz erweitern, um dies zu tun.
program Project1;
{$APPTYPE CONSOLE}
uses
Variants;
var
OriginalVarFromDynArray: procedure(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer);
OriginalVarToDynArray: procedure(var DynArray: Pointer; const V: Variant; TypeInfo: Pointer);
function DynArrayVarType(typeInfo: PDynArrayTypeInfo): Integer;
const
tkDynArray = 17;
begin
Result := varNull;
if (typeInfo<>nil) and (typeInfo.Kind=tkDynArray) then
begin
Inc(PChar(typeInfo), Length(typeInfo.name));
Result := typeInfo.varType;
if Result=$48 then
Result := varString;
end;
if (Result<=varNull) or (Result=$000E) or (Result=$000F) or ((Result>varInt64) and not (Result=varString)) then
VarCastError;
end;
procedure VarFromDynArray(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer);
var
VarType, DynDim: Integer;
begin
DynDim := DynarrayDim(PDynArrayTypeInfo(TypeInfo));
if DynDim=1 then
begin
//only attempt to deal with 1 dimensional arrays
if DynArray=nil then begin
VarClear(V);
VarType := DynArrayVarType(PDynArrayTypeInfo(TypeInfo));
if VarType = varString then
VarType := varOleStr;
V := VarArrayCreate([0, -1], VarType);
exit;
end;
end;
OriginalVarFromDynArray(V, DynArray, TypeInfo);
end;
procedure VarToDynArray(var DynArray: Pointer; const V: Variant; TypeInfo: Pointer);
var
DimCount: Integer;
Len: Integer;
begin
DimCount:= VarArrayDimCount(V);
if DimCount=1 then
begin
//only attempt to deal with 1 dimensional arrays
Len := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
if Len=0 then begin
DynArraySetLength(DynArray, PDynArrayTypeInfo(TypeInfo), 1, @Len);
exit;
end;
end;
OriginalVarToDynArray(DynArray, V, TypeInfo);
end;
procedure FixVariants;
var
VarMgr: TVariantManager;
begin
GetVariantManager(VarMgr);
OriginalVarFromDynArray := VarMgr.VarFromDynArray;
VarMgr.VarFromDynArray := VarFromDynArray;
OriginalVarToDynArray := VarMgr.VarToDynArray;
VarMgr.VarToDynArray := VarToDynArray;
SetVariantManager(VarMgr);
end;
type
TDynamicStringArray = array of string;
var
V: Variant;
sa: TDynamicStringArray;
begin
FixVariants;
sa := nil;
V := sa;
sa := V;
Writeln(Length(sa));
Readln;
end.
vielleicht Typumwandlung ist "Variante -> String -> Array von Strings" anstatt "Variante -> Zeiger -> Array von Strings" –