Question

Task:

Application written in Delphi accepts a structure (record in terms of Delphi) of three fields. I can send the pointer of this structure using SendMessage (Win32 API) function.

So a question is:

How to maintain certain structure representation in memory for Delphi in terms of Delphi?

It has type

PWPModPostData = ^ TWPModPostData;
TWPModPostData = record
   DataType: Integer;
   Data: PChar;
   Next: PWPModPostData;
end;

How to define it in C? I mean, is there any hidden or service fields in Delphi structures?

Was it helpful?

Solution

No, there are no hidden fields, and Delphi records and C structs can be mapped to each other 1:1, with a few caveats:

  • Don't use any data type C doesn't understand. This includes objects, dynamic arrays, and Delphi strings.

  • C and Delphi sometimes have different ideas about how to byte-align fields. Test your records and verify that they work on the C side. If they don't, try using packed record instead of record.

  • When passing a pointer to a record from C to Delphi or vice versa, make sure that the side receiving it doesn't try to free or reallocate the memory. It belongs to the memory manager that created it.

OTHER TIPS

Note that while you can certainly send the address of such a structure to another application as the LPARAM of a SendMessage() call it will most probably not work. The reason is that the same pointer will usually not point to the same physical memory location when used in another application with its own address range.

It works for a few Windows messages like WM_GETTEXT, and in these cases the OS does the necessary mapping behind the curtain, so that the receiving application can copy data to the buffer allocated by the calling application, and the address points to the same chunk of physical memory in both applications.

The same can be achieved by using the WM_COPYDATA message, which is intended to do the necessary marshalling of memory when doing data exchange between two applications.

But the structure in your question has another problem, because it contains pointers to memory. The WM_COPYDATA documentation explicitly states that this must not be done. While the address of the whole memory block will be modified to be valid in the receiving application the system can not know which parts of the memory block are pointers and would need to be mapped as well. All contained pointers will therefore be left as-is and be likely invalid. Your singly-linked list will be broken, and the PChar elements won't be accessible either.

Edit:

Regarding your comments: Above points are important only if you attempt to send messages from other applications; if you do this from a DLL things will work, because a DLL shares the address space of the process it was loaded into, so a pointer used in the application or any loaded DLL will always point to the same memory location. Sorry for any confusion this might have caused, but it wasn't obvious to me from your question that the data exchange happens inside one application.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top