访问 _CopyArray 过程

发布于 2024-08-30 09:24:50 字数 1890 浏览 5 评论 0原文

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

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

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

解决方案: 您需要通过将 _ 替换为 @ 并将其范围限定为 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;

Is there a way to access (and call) procedures like _CopyArray that are defined in the interface in the unit System?

NB: I am trying to create a routine that makes a deep clone of any dynamic array, and do not use Delphi 2010 (using Delphi 2007).

The reason why I am trying to solve this without using Copy is the fact that I have only a pointer where the dynamic array is located (the pointer that is) plus a typeinfo reference. I cannot call the Copy function because it implicitly needs to fill in the typeinfo.

SOLUTION:
You need to reference it by replacing the _ with an @ and scoping it with 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

や三分注定 2024-09-06 09:24:50

正如 Serg 和 Andreas 所说,_ 例程都使用编译器魔法来提供功能,因此您应该使用 Copy 而不是 _CopyArrayis 而不是_IsClass 等。

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

Like Serg and Andreas said, the _ routines all use compiler magic to provide functionality, so you should use Copy instead of _CopyArray, is instead of _IsClass, etc.

To directly answer your question though, no, there is no way to call those routines from Delphi code in other units. The makefile for the RTL passes an undocumented compiler switch when compiling System.pas and SysInit.pas which tells the compiler to convert any leading _ characters to @. _CopyArray becomes @CopyArray, for example. You can call it using a BASM (assembly) block, but that's it.

多情癖 2024-09-06 09:24:50

Andreas Rejbrand 的评论实际上是一个答案 - 当您复制复杂数组时,会自动调用 _CopyArray 过程。例如,在 _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;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文