Доступ к процедуре _CopyArray - PullRequest
3 голосов
/ 29 апреля 2010

Есть ли способ доступа (и вызова) процедур, таких как _CopyArray, которые определены в интерфейсе в модуле System?

Примечание: я пытаюсь создать процедуру, которая делает глубокий клон любого динамического массива, и не использую Delphi 2010 (с использованием Delphi 2007).

Причина, по которой я пытаюсь решить эту проблему без использования 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 ]

4 голосов
/ 29 апреля 2010

Как сказали Сергей и Андреас, все процедуры _ используют магию компилятора для обеспечения функциональности, поэтому вы должны использовать Copy вместо _CopyArray, is вместо _IsClass и т. Д.

Если прямо ответить на ваш вопрос, то нет, нет способа вызвать эти подпрограммы из кода Delphi в других единицах. При компиляции System.pas и SysInit.pas make-файл для RTL передает недокументированное переключение компилятора, которое указывает компилятору преобразовывать любые ведущие символы _ в @. Например, _CopyArray становится @CopyArray. Вы можете вызвать его, используя блок BASM (сборка), но это все.

3 голосов
/ 29 апреля 2010

Комментарий Андреаса Рейбранда - на самом деле ответ - процедура _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;
...