3

単位系のインターフェースで定義されている_CopyArrayのようなプロシージャにアクセス(および呼び出す)方法はありますか?

注意:動的配列のディープクローンを作成するルーチンを作成しようとしていますが、Delphi 2010を使用していません(Delphi 2007を使用)。

コピーを使用せずにこれを解決しようとしている理由は、動的配列が配置されているポインター(つまりポインター)とtypeinfo参照しかないためです。typeinfoを暗黙的に入力する必要があるため、Copy関数を呼び出すことができません。

解決策:_を@に置き換え、システムでスコープを設定して参照する必要があります。

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_CopyArray、の代わりに使用する必要があります。is_IsClass

しかし、あなたの質問に直接答えるために、いいえ、他のユニットのDelphiコードからそれらのルーチンを呼び出す方法はありません。RTLのmakefileは、System.pasおよびSysInit.pasをコンパイルするときに、文書化されていないコンパイラスイッチを渡します。これは、先頭の_文字を@に変換するようにコンパイラに指示します。たとえば、に_CopyArrayなります。@CopyArrayBASM(アセンブリ)ブロックを使用して呼び出すことができますが、それだけです。

于 2010-04-29T17:55:59.097 に答える
3

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;
于 2010-04-29T17:04:36.610 に答える