Có hai lỗi ở đây.
Trước hết là Variants.DynArrayVariantBounds
. Khi mảng động là nil
, lỗi này trả về một cặp giới hạn thấp/cao là (0, 0)
. Nó sẽ trả về (0, -1)
. Lỗi này được sửa trong các phiên bản mới nhất của Delphi. Điều đó làm cho V := sa
trả về một mảng biến thể với một phần tử đơn lẻ.
Lỗi thứ hai ảnh hưởng đến hướng khác, sa := V
. Lỗi này vẫn còn hiện diện trong các phiên bản mới nhất của Delphi. Lỗi này là trong Variants.DynArrayFromVariant
. Có một vòng lặp repeat/until
đi qua mảng biến thể đầu vào và điền vào mảng động đầu ra. Khi mảng biến thể đầu vào rỗng, nó không được nhập vào vòng lặp repeat/until
đó. Tuy nhiên, mã này thực hiện sai và cố đọc một phần tử của mảng biến thể với VarArrayGet
. Kể từ khi mảng là trống rỗng, mà gây ra một lỗi thời gian chạy. Tôi đã báo cáo điều này: QC#109445.
Đây là một mã rất đơn giản để sửa lỗi. Lưu ý rằng tôi chỉ xem xét trường hợp các mảng là một chiều. Nếu bạn cần hỗ trợ mảng chiều cao hơn thì bạn có thể mở rộng phương pháp này để làm như vậy.
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.
Nguồn
2012-10-11 08:44:20
có lẽ typecast là 'biến thể -> chuỗi -> mảng của chuỗi' thay vì' biến thể -> con trỏ -> mảng của chuỗi' –