【问题标题】:Why does COM Interop treat a VB6 Boolean as C# Short?为什么 COM Interop 将 VB6 布尔值视为 C# Short?
【发布时间】:2012-01-25 22:50:12
【问题描述】:

我有一个旧版 VB6 应用程序,它定义了以下结构:

Public Type DrawDown
    Date As Date
    Amount As Currency
    CapitaliseInterest As Boolean
End Type

使用tlbimp.exe 生成互操作程序集,但结构最终如下:

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct DrawDown
{
    public DateTime Date;
    [MarshalAs(UnmanagedType.Currency)]
    public decimal Amount;
    public short CapitaliseInterest;
}

我正在使用 .NET 4.0。

为什么 VB6 Boolean 被翻译成 C# short 而不是 bool

【问题讨论】:

  • 你确定你没有重新排序成员?
  • 我确定。 C# 是从 JustDecompile 中打开的程序集复制而来的。
  • 我对 VB6 不够熟悉,无法确定,但重新排序字段似乎是错误的。尽管 Davide 关于所涉及的实际类型的回答都是正确的,但无论哪种情况。
  • @JaredPar 自从我不得不深入研究 VB6 在幕后所做的事情已经有一段时间了,但我隐约记得,如果您更改字段的源顺序,它将尝试保持内存顺序以避免破坏二进制兼容性。不要相信我的话,正如我所说的那样已经有一段时间了。
  • @JonHanna:出于好奇,我使用 OleView 检查类型库中的布局。它与 VB6 源代码的顺序相匹配。奇怪的是,互操作程序集中的顺序发生了变化。

标签: c# .net com vb6 com-interop


【解决方案1】:

VB6 使用 VARIANT_BOOL 类型,

在此处查找有关它的信息和历史:BOOL vs. VARIANT_BOOL vs. BOOLEAN vs. boo

旁边出现了 VARIANT_BOOL。

typedef 短 VARIANT_BOOL;定义 VARIANT_TRUE ((VARIANT_BOOL)-1) 定义 VARIANT_FALSE ((VARIANT_BOOL)0) 这是由 Visual Basic 的人。 Basic 使用 -1 表示“真”,使用 0 表示 表示“假”,而 VARIANT_BOOL 旨在保留此 行为。

【讨论】:

    【解决方案2】:

    因为它是一个。

    VB6 布尔值是 16 位值,其中 0 为假,任何非零为真,但设置为真的值设置为 -1 (0xFFFF)。这样,许多布尔值与数字的组合在 VB6 中都能很好地工作,因为x AND TRUE 给出了xx OR FALSE 给出了xx AND FALSE 给出了FALSE 等等,对于按位具有相同的逻辑和布尔运算符。不幸的是,这也意味着 4 AND 2 是错误的,尽管它是 TrueThing AND OtherTrueThing,所以谨慎的 VB6 编码人员并没有过度依赖这一点,而是使用 CBool 将值强制为 0 或 -1。

    一般来说,我们可以选择使用自然机器大小来提高机器处理速度,而不是使用单个字节,因为它是最小的可寻址单元,因此具有大小优势。当 16 位机器上的自然大小当然是 16 位时,与今天我们拥有 32 位和 64 位机器时相比,平衡更倾向于自然大小。 Visual Basic 1.0 在 DOS 和 Windows 3.0 上运行,后者可以在 Intel 80286 16 位处理器上运行,所以选择并不奇怪。

    在 COM 世界中,我们有 VARIANT_BOOL,这只是“一个布尔值,按照 VB6 的方式完成”的另一种说法,以实现跨语言的兼容性。 C# 中最接近的东西是 shortushort,如果我们只关心 C#,我们可以选择其中任何一个。首先,虽然我们倾向于使用带符号的值而不是无符号的值,这会使我们倾向于short,但ushort 不是符合 CLS 的类型,并且在获取时引入与其他 .NET 语言的不兼容性几乎没有任何意义兼容COM!因此short 是明确的选择。

    【讨论】:

      【解决方案3】:

      Boolean 本质上是一个短整数:

      False = 0, True != 0
      

      生成互操作程序集可以解决此问题。

      MSDN 的文档。

      4 字节整数值,其中任何非零值表示真和 0 代表虚假。这是布尔字段的默认格式 结构和平台调用调用中的布尔参数。

      【讨论】:

        【解决方案4】:

        您可以将 /VariantBoolFieldToBool 标志传递给 tlbimp.exe,使其生成 C# bool 成员而不是 short。

        official documentation for tlbimp.exe

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-15
          • 1970-01-01
          相关资源
          最近更新 更多