Delphi перечисляет вариант как varInteger вместо varUInt32 - PullRequest
0 голосов
/ 23 октября 2018

Значения перечисления Delphi изначально определены как целые числа без знака - 1, 2 или 4 байта, в зависимости от настройки MINENUMSIZE.

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

Есть ли способ настроитьавтоматическое преобразование варианта, что значения перечисления будут преобразованы в varInteger вместо varUInt32?

Фон: мы пишем код библиотеки для OPC UA.OPC UA определяет тип с именем Variant, который имеет историю в Windows Variant, но теперь определяется по-другому.На практике OPC UA определяет, что значения перечисления передаются как Int32 по проводам.

OPC UA также определяет тип данных с именем DataValue, который состоит из Value (как вариант), StatusCode (UInt32) и некоторой метки времениfields.

Теперь мы используем Delphi Variants для отображения OPC UA Variant, так как в целом он работает хорошо.Теперь единственной серьезной ошибкой является то, что когда вы записываете значение перечисления в Variant, оно преобразуется в UInt32, тогда как OPC UA ожидает Int32.

Библиотека принимает варианты (в DataValues) и как разработчик приложения, выможно просто присвоить значения перечисления для DataValue, и все выглядит хорошо.Однако значение было преобразовано в UInt32, и когда код библиотеки видит этот вариант, он больше не может знать, что он фактически соответствует типу перечисления переменной.

Если мы сможем контролировать автоматическое преобразование (илина самом деле это родной тип данных перечислений), мы могли бы просто избавиться от этой проблемы.

Если это невозможно, нам действительно придется изобретать код преобразования везде, где мы можем, но который никогда не может бытьВ конце концов, на 100%.

1 Ответ

0 голосов
/ 23 октября 2018

Вы не можете различить присвоение перечисляемого типа варианту и присвоение целочисленного типа варианту.Рассмотрим следующий код:

uses
  System.SysUtils;

type
  TFoo = (foo, bar);

var
  V: Variant;
  enum: TFoo;
  b: Byte;

begin
  V := enum;
  V := b;
end.

Компилятор генерирует следующее:

Project52946989.dpr.14: V := enum;
00422562 B8389F4200       mov eax,$00429f38
00422567 33D2             xor edx,edx
00422569 8A15489F4200     mov dl,[$00429f48]
0042256F B101             mov cl,$01
00422571 E8BED1FFFF       call @VarFromInt
Project52946989.dpr.15: V := b;
00422576 B8389F4200       mov eax,$00429f38
0042257B 33D2             xor edx,edx
0042257D 8A15499F4200     mov dl,[$00429f49]
00422583 B101             mov cl,$01
00422585 E8AAD1FFFF       call @VarFromInt

Так что даже если вы подключите библиотечную подпрограмму, которая обрабатывает такое назначение (System.Variants._VarFromInt), вы будетенеизбежно получит присваивания значений Byte, а также значений перечислимого типа.

Приведенный выше код предполагает размер однобайтового перечисляемого типа, но ничего не меняется для 2 или 4-байтового перечисляемого типа.Вместо того, чтобы присвоение выглядело как байтовое присваивание, оно выглядит как присваивание Word или LongWord соответственно.

...