質問
タスク:
Delphi で書かれたアプリケーションは構造体 (record
Delphi の観点から)3 つのフィールドの。次を使用してこの構造体のポインタを送信できます SendMessage
(Win32 API) 関数。
そこで質問は次のとおりです。
Delphi に関して、Delphi のメモリ内に特定の構造表現を維持するにはどうすればよいですか?
タイプがあります
PWPModPostData = ^ TWPModPostData;
TWPModPostData = record
DataType: Integer;
Data: PChar;
Next: PWPModPostData;
end;
Cでどうやって定義するのでしょうか?つまり、Delphi 構造に隠しフィールドやサービス フィールドはあるのでしょうか?
解決
いいえ、隠しフィールドはありません。Delphi レコードと C 構造体は相互に 1:1 でマッピングできますが、いくつかの注意点があります。
データ型Cが理解していないデータを使用しないでください。これには、オブジェクト、動的配列、Delphi文字列が含まれます。
CとDelphiは時々異なる フィールドをバイトアラインする方法に関するアイデア。レコードをテストし、次のことを確認します それらはC側で動作します。もし彼らが しないで、 パックされたレコードの代わりに 記録.
レコードへのポインタを渡す場合 C から Delphi へ、またはその逆の場合は、 それを受け取る側が 解放や再割り当ては試みません 記憶。それは記憶に属します それを作成したマネージャー。
他のヒント
このような構造体のアドレスを別のアプリケーションに送信できることは確かですが、 LPARAM
の SendMessage()
呼び出してもおそらく機能しません。その理由は、同じポインタが独自のアドレス範囲を持つ別のアプリケーションで使用される場合、通常は同じ物理メモリの場所を指さないためです。
次のようないくつかの Windows メッセージに対して機能します。 WM_GETTEXT
, このような場合、OS はカーテンの後ろで必要なマッピングを実行し、受信側アプリケーションが呼び出し側アプリケーションによって割り当てられたバッファにデータをコピーできるようにし、アドレスは両方のアプリケーションの物理メモリの同じチャンクを指します。
同じことは、 WM_COPYDATA
このメッセージは、2 つのアプリケーション間でデータ交換を行うときに必要なメモリのマーシャリングを行うことを目的としています。
しかし、質問の構造にはメモリへのポインタが含まれているため、別の問題があります。の WM_COPYDATA
ドキュメントには、これを行ってはいけないと明示的に記載されています。メモリ ブロック全体のアドレスは受信アプリケーションで有効になるように変更されますが、システムはメモリ ブロックのどの部分がポインタであるかを知ることができないため、同様にマップする必要があります。したがって、含まれるすべてのポインターはそのまま残され、無効になる可能性があります。単一リンクのリストは壊れ、 PChar
要素にもアクセスできなくなります。
編集:
あなたのコメントに関して:上記の点は、他のアプリケーションからメッセージを送信しようとする場合にのみ重要です。DLL からこれを実行すると、DLL がロードされたプロセスのアドレス空間を共有するため、動作します。そのため、アプリケーションまたはロードされた DLL で使用されるポインタは、常に同じメモリ位置を指すことになります。混乱を引き起こして申し訳ありませんが、データ交換が 1 つのアプリケーション内で行われることは、質問からは明らかではありませんでした。