3

有没有办法访问(和调用)像 _CopyArray 这样在单元系统的接口中定义的过程?

注意:我正在尝试创建一个对任何动态数组进行深度克隆的例程,并且不使用 Delphi 2010(使用 Delphi 2007)。

我试图在不使用 Copy 的情况下解决这个问题的原因是我只有一个动态数组所在的指针(即指针)加上一个 typeinfo 引用。我无法调用 Copy 函数,因为它隐式需要填写 typeinfo。

解决方案:您需要通过将 _ 替换为 @ 并将其范围限定为 system 来引用它。

procedure CopyArray( dest, source, typeInfo: Pointer; cnt: Integer );
asm
    PUSH    dword ptr [EBP+8]
    CALL    system.@CopyArray
end;

type
    PObject = ^TObject;

function TMessageRTTI.CloneDynArray( Source: Pointer; T: TTypeRecord ): Pointer;
var
    TypeInfo: TTypeRecord;
    L:        Integer;
    PObj:     PObject;
    PArr:     PPointer;
begin
    Assert( T.TypeKind = tkDynArray );

    // set size of array
    Result := nil;
    L := Length( TIntegerDynArray( Source ) );
    if L = 0 then Exit;
    DynArraySetLength( Result, T.TypeInfo, 1, @L );

    if Assigned( T.TypeData^.elType ) then TypeInfo := ByTypeInfo( T.TypeData^.elType^ ) else TypeInfo := nil;
    if Assigned( TypeInfo ) then begin
        case TypeInfo.TypeKind of
            tkClass: begin
                PObj := Result;
                while L > 0 do begin
                    PObj^ := CloneObject( PObject( Source )^ );
                    Inc( PObject( Source ) );
                    Inc( PObj );
                    Dec( L );
                end;
            end;
            tkDynArray: begin
                PArr := Result;
                while L > 0 do begin
                    PArr^ := CloneDynArray( PPointer( Source )^, TypeInfo );
                    Inc( PPointer( Source ) );
                    Inc( PArr );
                    Dec( L );
                end;
            end;
            else CopyArray( Result, Source, TypeInfo.TypeInfo, L );
        end;
    end else begin
        // We can simply clone the data
        Move( Source^, Result^, L * T.ElementSize );
    end;
end;
4

2 回答 2

4

就像 Serg 和 Andreas 说的,_ 例程都使用编译器魔法来提供功能,所以你应该使用Copy而不是_CopyArrayis而不是_IsClass,等等。

但是,要直接回答您的问题,不,无法从其他单元的 Delphi 代码中调用这些例程。RTL 的生成文件在编译 System.pas 和 SysInit.pas 时传递了一个未记录的编译器开关,它告诉编译器将任何前导 _ 字符转换为 @。例如,_CopyArray变成。@CopyArray您可以使用 BASM(程序集)块来调用它,仅此而已。

于 2010-04-29T17:55:59.097 回答
3

The comment by Andreas Rejbrand is actually an answer - the _CopyArray procedure is called automaticaly when you copy complicated arrays. For example, set a breakpoint in _CopyArray and run the following code (should be compiled with debug .dcu to activate the breakpoint):

procedure TForm1.Button4Click(Sender: TObject);
type
  TArr2D = array of TBytes;

var
  A, B: TArr2D;

begin
  A:= TArr2D.Create(TBytes.Create(1, 2, 3), TBytes.Create(4, 5));
  B:= Copy(A);
  Button4.Caption:= IntToStr(B[1, 1]);
end;
于 2010-04-29T17:04:36.610 回答