두 가지 버그가 있습니다.
우선 Variants.DynArrayVariantBounds
. 동적 배열이 nil
일 때이 오류는 (0, 0)
의 낮은/높은 경계 쌍을 잘못 반환합니다. (0, -1)
을 반환해야합니다. 이 버그는 최신 버전의 Delphi에서 수정되었습니다. 이로 인해 V := sa
은 하나의 빈 요소가있는 변형 배열을 반환합니다.
두 번째 버그는 다른 방향 인 sa := V
에 영향을줍니다. 이 버그는 최신 버전의 Delphi에서 계속 나타납니다. 이 버그는 Variants.DynArrayFromVariant
에 있습니다. repeat/until
루프가 입력 변형 배열을 거쳐 출력 동적 배열을 채 웁니다. 입력 변형 배열이 비어있는 경우 해당 배열에 repeat/until
루프를 입력하면 안됩니다. 그러나이 코드는 실수로 VarArrayGet
을 사용하여 변형 배열의 요소를 읽으려고 시도합니다. 배열이 비어 있기 때문에 런타임 오류가 발생합니다. 나는 이것을보고했다 : QC#109445.
다음은 버그를 수정하는 매우 간단한 코드입니다. 배열이 1 차원 인 경우만을 고려해야합니다. 고 차원 배열을 지원해야하는 경우이 방법을 확장하여 그렇게 할 수 있습니다.
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.
아마도 타입 변환은 'variant -> pointer -> 문자열 배열'대신에 'variant -> string -> array of arrays'입니다. –