Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Чародей Ученика
Guest
Доброй ночи! Подскажите пожалуйста, а как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?

Условный пример. Допустим имеется процедура:
procedure AddTypeKind(ForkIndex: UInt32; NewTypeKind: TTypeKind; SubIndex: Cardinal = 0; BaseTypeKinds: TTypeKinds = []; Additional: DWORD = 0);

Есть люди, которые хотят вызывать её из своих "богомерзких плюсов" C++. Но как им объявлять заголовок?
Точнее - второй и четвёртый параметры функции (учитывая что при изменении количества элементов в TTypeKind размеры обеих переменых могут меняться)?

Я не собираюсь менять нужный мне тип из-за кого-то там - во-первых мне просто нет необходимости это делать (пользы не будет, наоборот станет хуже) моему коду безразлично как они передаются, во-вторых даже если стану править то на рефакторинг потрачу месяцы.
Крутить "обёртки/переходники" мне тоже некогда, да и система слишком большая. Но если бы было достаточно просто добавить какие-нибудь директивы вроде $MinEnumSize или stdcall - я бы уж потратил час/два чтоб их расставить, так уж и быть.

Люди сильно просят - и я (хоть и не особо заинтересован в их "удобстве", я вообще был против сования рук со стороны в мою систему) согласился рассмотреть есть ли возможность что-то для них подправить. Их бы устроило что-то вроде:
void AddTypeKind(int32, DWORD, DWORD, DWORD, DWORD);

Иными словами надо чтоб параметры #2 и #4 были грубо говоря "по смещению" 4 и 12. А в справке пишут:
Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values.

Вывод - передаётся не так как хотели бы люди (и плюс не совсем понятно что будет при передаче трёхбайтового множества). А можно ли принудительно заставить всегда быть 32bit?

Был совет использовать для перечисления директиву {$MINENUMSIZE 4} (в принципе подходит и работает), а для множества добавлять в перечисление холостой элемент с явным указанием значения в 31.
Но последнее хоть и даёт нужный эффект, но лишает перечисление генерации type info, что к сожалению в моём случае никак не подходит.

P.S. Насколько я протестировал - все мои типы не превышают 4 байта, так что ситуацию с превышением можно опустить.
12 июл 18, 00:00    [21564493]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
MBo
Member

Откуда:
Сообщений: 61
Чародей Ученика,

А на что ты готов пойти ради совместимости?
Например, в таком виде в 32-разрядных Windows функцию произвольные
сишники не вызовут - им нужно общеизвестное соглашение о вызове - stdcall или cdecl.
(В Win64 соглашение о вызове единое). Так что тебе уже, скорее всего, придётся модифицировать код.

Далее - хорошо бы знать сценарий использования, и что может из себя представлять TTypeKind
12 июл 18, 09:35    [21564874]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10598
Передавайте не множество, а битовую маску. Если элементами множества могут быть только 32 элемента, то хватит DWORD
12 июл 18, 11:04    [21565266]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Соколинский Борис
Member

Откуда: Москва
Сообщений: 8565
Чародей Ученика
Я не собираюсь менять нужный мне тип из-за кого-то там - во-первых мне просто нет необходимости это делать (пользы не будет, наоборот станет хуже) моему коду безразлично как они передаются, во-вторых даже если стану править то на рефакторинг потрачу месяцы.

OK, забываем про плюсы и рассматриваем ситуацию в общем. Что произойдет с программой, написанной на самых каноничных дельфях, если в используемой ей dll внезапно поменялся размер параметра? Правильно, сначала улетит в космос, потом упадет. И кое-кто заслуженно огребет.
Вывод - плюсы тут совершенно не причем, при взаимодействии бинарников размеры должны быть фиксированными всегда.

Чародей Ученика
Но последнее хоть и даёт нужный эффект, но лишает перечисление генерации type info, что к сожалению в моём случае никак не подходит.

Очень даже подходит, Просто нужно использовать подтипы. Вроде
Type
  TItemExt=(I0=0, I1=1, IDummy=31); 
  TItemsExt=set of  TItemExt
  TItemInt=(I0..I1);
  TItemsInt=set of TItemInt;
12 июл 18, 11:08    [21565293]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
527470
Member

Откуда:
Сообщений: 22
Чародей Ученика
Но последнее хоть и даёт нужный эффект, но лишает перечисление генерации type info, что к сожалению в моём случае никак не подходит.


Вообще ты можешь сам посчитать сколько занимает множество, не обязательно задавать руками планку в 31, просто подсчитай размер перечисления и его используй. Если у тебя 8 значений в TTypeKind то у перечисления размер будет байт, и вообще размер = (<кол-во элементов> + 7) div 8. Это если у тебя элементы автоматически нумеруются. Проблема будет только когда ты будешь расширять перечисление, то нужно проверять размер множества, а если ты сразу задашь 31, то размер всегда будет dword.
12 июл 18, 12:54    [21565790]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Василий 2
Member

Откуда:
Сообщений: 239
Размеры типов не динамические, а определяются на этапе компиляции. Следовательно, делаешь экспортируемую функцию GetEnumSize = SizeOf(TTypeKind), а сишники делают так (псевдокодом)
typedef PasEnum int16 // (к примеру) определено эмпирически вызовом того же GetEnumSize из текущего Delphi бинарника
if SizeOf(PasEnum) <> GetEnumSize throw Error('Размер отличается от ожидаемого')

ну и потом вызывают функцию

PasEnum TypeKind = 2;
AddTypeKind(.. , TypeKind, ..)

а множества соответственно генерят как битовую маску, тоже с проверкой размера.
В этом случае в твоем коде даже не надо ничего переделывать, кроме добавления одной функции, только помнить, что перетасовывать значения внутри TTypeKind уже надо с оглядкой на других. Если размер типа изменится, то старая версия программы при попытке подключиться к новой DLL выкинет ошибку.
12 июл 18, 14:47    [21566133]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
зонд
Guest
Соглашение о вызове "cdecl" - аргументы, размер которых меньше 4-х байт, расширяются до 4-х байт.
Оно?

А про "stdcall" сходу не нашёл, но помнится там что-то также расширялось или выравнивалось, можно и его опробовать.
12 июл 18, 15:41    [21566324]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1161
В С++ размер перечислимого типа 4 байта.. В Delphi по умолчанию 1 байт.. но это решается {$MINENUMSIZE 4}
А также для структур {$ALIGN ON}
12 июл 18, 17:08    [21566687]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10598
X-Cite
В С++ размер перечислимого типа 4 байта..
С какого перепугу? Он совместим с типом int а вот размер может зависеть от реализации
12 июл 18, 17:19    [21566726]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
schi
Member

Откуда: Москва
Сообщений: 2601
зонд
Соглашение о вызове "cdecl" - аргументы, размер которых меньше 4-х байт, расширяются до 4-х байт.
Оно?


Это при любом соглашении в 32-х битных программах. Аналогично, в 64-битных расширяются до 64 бит.
12 июл 18, 19:04    [21567056]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
527470
Member

Откуда:
Сообщений: 22
schi,

Так-то оно так, но это влияет только на передачу параметров. А вот использоваться будет не все 32 бита, и при отправке $100 в 1 байтное множества будет расцениваться принимающей программой как 0, т.е. [], из-за этого не будет возможным проверить правильность получаемых данных. Потому в описании функции стоит указывать верный размер, дабы уже на вызывающей стороне можно было проверить хотя бы выход за границы.
12 июл 18, 19:13    [21567082]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6270
Чародей Ученика,

что насчет множеств, можно передавать по идее в любом виде (хоть массива), но на другой стороне сделать обертку, переводящую в родной формат.
12 июл 18, 19:39    [21567124]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
зонд
Guest
schi
Это при любом соглашении в 32-х битных программах. Аналогично, в 64-битных расширяются до 64 бит.

Не-а. При "register/fastcall" байт передаётся в AL/DL а слово в AX/DX - остальное будет с мусором. Да и в стеке тоже будет в виде 8/16 бит + мусор.
12 июл 18, 23:51    [21567480]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Чародей Ученика
Guest
MBo
А на что ты готов пойти ради совместимости?
Я уже написал - на мелкие правки вроде добавления директив, например.

Соколинский Борис
Просто нужно использовать подтипы. Вроде
Type
  TItemExt=(I0=0, I1=1, IDummy=31); 
  TItemsExt=set of  TItemExt
  TItemInt=(I0..I1);
  TItemsInt=set of TItemInt;
Может у вас версия Делфи какая-то более современная, но а у меня:
[dcc32 Error] : E2004 Identifier redeclared: 'I0'

527470
Вообще ты можешь сам посчитать сколько занимает множество, не обязательно задавать руками планку в 31, просто подсчитай размер перечисления и его используй.
Мне не требуется считать, задавать планку, знать размер. Это некоторые люди просят "задать планку". Мне-то всё равно, а у них неудобства. Если им можно помочь без доп.разработок - то почему бы и нет?

Василий 2
В этом случае ...
Спасибо, возможно сделаем как запасной вариант.

X-Cite
но это решается {$MINENUMSIZE 4}
У меня в первом посте уже есть про это, решает задачу но частично - не влияет на Set.
И вообще даже просто по логике - если есть $MinEnumSize, почему нету $MinSetSize? Недоработка))

зонд
Оно?
... можно и его опробовать.
Благодарю, попробую указать как cdecl!
13 июл 18, 11:28    [21568182]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Соколинский Борис
Member

Откуда: Москва
Сообщений: 8565
Чародей Ученика
Может у вас версия Делфи какая-то более современная, но а у меня:
[dcc32 Error] : E2004 Identifier redeclared: 'I0'
Проблема не в клозетах, а в головах в версии дельфей.
Когда понимаешь о чем речь, ошибки синтаксиса исправляются самостоятельно.
  TItemExt=(I0=0, I1=1, IDummy=31); 
  TItemsExt=set of  TItemExt;
  TItemInt= I0..I1;
  TItemsInt=set of TItemInt;

Тип TItemsInt используется во внутренних операциях, TItemsExt - во внешних. Компилятор сам сделает нужные преобразования размеров.
13 июл 18, 11:54    [21568310]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
Чародей Ученика
Guest
гм... "Перечисление", "имена элементов", "скобки"... Последнее показалось логичным и не лишним... А оно уже не как имена, а как константы, ясно.

Хоть при попытке присвоить TItemInt неподдерживаемый (отсутствующий) элемент получаю:
[dcc32 Error] : E1012 Constant expression violates subrange bounds
но при добавлении в TItemsInt неподдерживаемого (отсутствующего) элемента - не добавляет, но совершенно молча.
Плюс в Code Completion отображаются все лишние, "дырявым" не сделать, а у TItemInt - no type info.

Подход действительно интересный, спасибо, но в моём случае судя по всему не подойдёт.
13 июл 18, 13:02    [21568593]     Ответить | Цитировать Сообщить модератору
 Re: Как передаются типы данных перечисление и множество и можно ли на это как-то повлиять?  [new]
527470
Member

Откуда:
Сообщений: 22
Чародей Ученика
Мне не требуется считать, задавать планку, знать размер. Это некоторые люди просят "задать планку". Мне-то всё равно, а у них неудобства. Если им можно помочь без доп.разработок - то почему бы и нет?


Так и задаёте планку, один раз посчитайте размер и скажите им какой он у вас. Какие ещё доп. разработки? В моём варианте решения, у вас не изменится ни одной строчки кода на делфи.
15 июл 18, 12:26    [21571808]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить