Delphi Records и C Structs - PullRequest
       26

Delphi Records и C Structs

3 голосов
/ 07 декабря 2009

Задача:

Приложение, написанное на Delphi, принимает структуру (record в терминах Delphi) из трех полей. Я могу отправить указатель этой структуры, используя функцию SendMessage (Win32 API).

Итак, вопрос:

Как сохранить определенное представление структуры в памяти для Delphi в терминах Delphi?

имеет тип

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

Как определить это в C? Я имею в виду, есть ли скрытые или служебные поля в структурах Delphi?

Ответы [ 2 ]

9 голосов
/ 07 декабря 2009

Нет, скрытых полей нет, и записи Delphi и структуры C могут быть сопоставлены друг с другом 1: 1 с несколькими оговорками:

  • Не используйте данные типа C не Понимаю. Это включает в себя объекты, динамические массивы и строки Delphi.

  • C и Delphi иногда имеют разные идеи о том, как выравнивать байты полей. Проверьте свои записи и убедитесь, что они работают на стороне C. Если они нет, попробуйте использовать упакованную запись вместо запись .

  • При передаче указателя на запись из C в Delphi или наоборот, сделать уверен, что сторона, получающая его не пытается освободить или перераспределить объем памяти. Принадлежит памяти менеджер, который его создал.

4 голосов
/ 07 декабря 2009

Обратите внимание, что хотя вы, безусловно, можете отправить адрес такой структуры в другое приложение, например, LPARAM при вызове SendMessage(), он, скорее всего, не будет работать. Причина в том, что один и тот же указатель обычно не будет указывать на одно и то же место в физической памяти при использовании в другом приложении с собственным диапазоном адресов.

Он работает для нескольких сообщений Windows, таких как WM_GETTEXT, и в этих случаях ОС выполняет необходимое отображение за кулисами, чтобы принимающее приложение могло копировать данные в буфер, выделенный вызывающим приложением, и точки адреса к одному и тому же куску физической памяти в обоих приложениях.

То же самое можно сделать с помощью сообщения WM_COPYDATA, которое предназначено для выполнения необходимой сортировки памяти при выполнении обмена данными между двумя приложениями.

Но у структуры в вашем вопросе есть другая проблема, потому что она содержит указатели на память. В документации WM_COPYDATA прямо указано, что этого делать нельзя. В то время как адрес всего блока памяти будет изменен, чтобы быть действительным в принимающем приложении, система не может знать, какие части блока памяти являются указателями, и их также необходимо отобразить. Поэтому все содержащиеся в нем указатели будут оставлены как есть и, вероятно, будут недействительными. Ваш односвязный список будет разбит, а элементы PChar также не будут доступны.

Edit:

По поводу ваших комментариев: Вышеуказанные пункты важны только в том случае, если вы пытаетесь отправлять сообщения из других приложений; если вы делаете это из DLL, все будет работать, потому что DLL разделяет адресное пространство процесса, в который она была загружена, поэтому указатель, используемый в приложении или любой загруженной DLL, всегда будет указывать на одно и то же место в памяти. Извините за путаницу, которая могла возникнуть, но из вашего вопроса мне не было очевидно, что обмен данными происходит внутри одного приложения.

...