代码之家  ›  专栏  ›  技术社区  ›  Ritsaert Hornstra

访问\u CopyArray过程

  •  3
  • Ritsaert Hornstra  · 技术社区  · 16 年前

    有没有一种方法可以访问(和调用)单元系统接口中定义的过程,如\u CopyArray?

    注意:我试图创建一个例程,对任何动态数组进行深度克隆,并且不使用delphi2010(使用delphi2007)。

    我之所以不使用Copy来解决这个问题,是因为我只有一个动态数组所在的指针(即指针)和一个typeinfo引用。我无法调用Copy函数,因为它隐式地需要填写typeinfo。

    解决方案:

    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;
    
    2 回复  |  直到 16 年前
        1
  •  4
  •   Zoë Peterson RRUZ    16 年前

    正如Serg和Andreas所说,例程都使用编译器的魔力来提供功能,因此您应该使用 Copy 而不是 _CopyArray , is _IsClass

    不过,要直接回答您的问题,不,在其他单元中无法从Delphi代码调用这些例程。RTL的makefile在编译System.pas和SysInit.pas时传递一个未记录的编译器开关,它告诉编译器将任何前导字符转换为@。 _复制数组 变成 @CopyArray

        2
  •  3
  •   kludg    16 年前

    Andreas Rejbrand的评论实际上是一个答案—复制复杂数组时,\u CopyArray过程称为automaticaly。例如,在\u CopyArray中设置断点并运行以下代码(应使用debug.dcu编译以激活断点):

    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;