运行时创建类型指针?

时间:2017-03-29 15:34:54

标签: delphi pointers record

是否有办法在运行时创建一个指向记录的类型指针?

E.g。在运行时实现与

中的pMyRecord赋值相同
TMyRecord = record
  s1: string;
  s2: string;
end;

TpMyRecord = ^TMyRecord;

...

 var pMyRecord: TpMyRecord;
 begin
   New(pMyRecord)

但没有TpMyRecord = ^TMyRecord声明。

我知道我可以使用GetMem和FreeMem但我希望保持字符串的生命周期管理。

我知道问题就在那里,我可以使用TpMyRecord = ^TMyRecord声明,但我很好奇是否有运行时间方式(尽管我&#39 ; m怀疑它对RTTI的麻烦太多了。)

1 个答案:

答案 0 :(得分:3)

这可能有点诡计。这是一个演示程序:

{$APPTYPE CONSOLE}

uses
  TypInfo;

type
  PMyRecord = ^TMyRecord;
  TMyRecord = record
    s1: string;
    s2: string;
  end;

var
  SystemNew: function(Size: NativeInt; TypeInfo: Pointer): Pointer;
  SystemDispose: procedure(P: Pointer; TypeInfo: Pointer);

function GetSystemNewAddress: Pointer;
asm
  MOV EAX, offset System.@New
end;

function GetSystemDisposeAddress: Pointer;
asm
  MOV EAX, offset System.@Dispose
end;

var
  p: PMyRecord;
  typeInfo: Pointer;

begin
  ReportMemoryLeaksOnShutdown := True;

  @SystemNew := GetSystemNewAddress;
  @SystemDispose := GetSystemDisposeAddress;

  typeInfo := System.TypeInfo(TMyRecord);
  p := SystemNew(TypInfo.GetTypeData(typeInfo).RecSize, typeInfo);
  p.s1 := 'foo';
  p.s2 := 'bar';
  SystemDispose(p, typeInfo);
end.

New函数是一个内部函数,并从编译器接受特殊处理。当您调用New时,编译器会发出代码来调用System._New来传递类型的大小及其类型信息。反过来System._New使用类型的大小分配内存,然后使用类型信息初始化实例。

上面程序中的代码显示了如何从代码中进行调用。棘手的部分是获得System._New的地址。这里的代码显示了如何为32位Windows编译器执行此操作。

如果您想致电New,您还需要致电Dispose。这也是一种内在的,并且处理得非常相似。上面的代码显示了如何。

不言而喻,这依赖于将来可能会发生变化的实施细节。