Delphi枚举变量为varInteger而不是varUInt32

时间:2018-10-23 10:40:50

标签: delphi enums variant

根据MINENUMSIZE的设置,Delphi枚举值本机定义为无符号整数-1、2或4个字节。

我有一种情况,我们使用Variant在应用程序之间传输不同数据类型的数据。所有其他数据类型都可以很好地工作,但是现在我们意识到其他应用程序的期望是枚举值应该是带符号的整数而不是无符号的(有些确实在对此进行验证)。

是否有一种方法可以配置自动变量转换,以将枚举值转换为varInteger而不是varUInt32?

背景:我们正在为OPC UA编写库代码。 OPC UA定义了一种称为Variant的类型,该类型在Windows Variant中具有历史记录,但现在以不同的方式进行了定义。实际上,OPC UA定义枚举值通过网络传输为Int32。

OPC UA还定义了一种称为DataValue的数据类型,它由Value(作为变量),StatusCode(UInt32)和一些Timestamp字段组成。

现在,我们正在使用Delphi Variants映射OPC UA Variant,因为它通常可以很好地工作。现在唯一的主要陷阱是,当您将一个枚举值写入Variant时,它将转换为UInt32,而OPC UA则期望Int32。

该库采用Variants(在DataValues中),作为应用程序开发人员,您只需将枚举值分配给DataValue,一切看起来就很好。但是,该值已转换为UInt32,并且当库代码看到此Variant时,它不再知道它实际上对应于变量的枚举类型。

我们应该能够控制自动转换(或者实际上是枚举的本机数据类型),就可以解决这个问题。

如果这是不可能的,那么我们将真的必须在任何可能的地方发明转换代码,但是毕竟不可能永远100%确定。

1 个答案:

答案 0 :(得分:3)

您无法区分将枚举类型分配给变量,还是将整数类型分配给变量。考虑以下代码:

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字节枚举类型没有太大变化。代替看起来像字节分配的分配,它看起来像分别是WordLongWord的分配。