2017-03-29 7 views
1

実行時にレコードへの型付きポインタを作成する方法はありますか?型付きポインタの実行時作成ですか?

など。 ...

TMyRecord = record 
    s1: string; 
    s2: string; 
end; 

TpMyRecord = ^TMyRecord; 

var pMyRecord: TpMyRecord; 
begin 
    New(pMyRecord) 

が、その後TpMyRecord = ^TMyRecord宣言なしにpMyRecordの割り当てなどのランタイムで同じことを実現します。

私はGetMemとFreeMemのを使用することができます知っているが、私は、文字列の寿命管理を維持したいです。

質問は多少ありますが、私はちょうどTpMyRecord = ^TMyRecord宣言を使用することができますが、これを実行する方法があれば興味があります(ただし、 RTTIの面倒な作業の多く)。

+2

'var pMyRecord:^ TMyRecord;'は、ポインタ型を明示的に宣言せずに修正します。 –

+0

私はその質問を理解していません。存在があった場合、これをどのように使用するかの例を挙げることができますか?実行時まで型が分からない変数に対して 'New'を呼び出す必要があるのはどこですか? –

+0

@RobKennedy実際には、特定の図書館の消費者が余分な宣言をする必要はありません。そうすれば、その余分なステップを踏まなければならなくなります。プログラマは怠惰です。 ;) – Domus

答えて

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 [email protected] 
end; 

function GetSystemDisposeAddress: Pointer; 
asm 
    MOV EAX, offset [email protected] 
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を呼び出すことになるでしょう。これも本質的であり、同様に扱われます。上記のコードは、どのように表示されます。

これは、今後変更される実装の詳細に依存していることは言うまでもないでしょう。

+0

これは* "TpMyRecord =^TMyRecord'宣言" *? –

+0

それはクレイジー優れた魔法です。あなたはスタンバイでその答えを持っていたのですか、それともそれを解決しましたか?いずれにせよ、それはとても印象的です。どうもありがとう! – Domus

+0

@ sertac私は、レコードに割り当てるのが便利なようにそれを含めました。私はその部分の実行時のメカニズムを構築しようとするのに気にすることができませんでした。そして、それが役に立ちそうなシナリオを想像するのに苦労します。明らかに、NewとDisposeの呼び出しは、その型宣言に依存していません。 –

関連する問題