2

在 COM 对象的 IDL 中,我执行以下操作:

enum TxMyFlags
{
,    flagOption = 1,
,    flagOtherOption = 2,
,    flagMoreOption = 4,
,    flagAnotherFlag = 8,
,    flagExtra = 128
// etc.
};

并且具有可以获取标志的总和(或按位或,相同的东西)的函数,例如(在 IDL 中)

HRESULT _stdcall a_method([in] enum TxMyFlags);

预期用途的示例是:

a_method( flagExtra | flagMoreOption );

它似乎有效,但实际上是否允许这样做,或者 RPC 传输或任何可能会拒绝不完全在枚举定义中的枚举参数值?

4

1 回答 1

4

如果您的客户端和服务器正在处理中(并且没有发生真正的混编,不涉及 RPC),您将不会看到任何问题,因为枚举,无论您如何定义它,都将被视为它的 int/long/whatever 整数类型等价物在尺寸方面。

因此,进程外(或跨公寓编组)案例可能是一个问题。在这种情况下,如文档中所述:枚举属性(以及您的评论):

enum 类型的对象是 int 类型,它们的大小取决于系统。默认情况下,枚举类型的对象在通过网络传输时被视为 unsigned short 类型的 16 位对象。0 - 32,767 范围之外的值会导致运行时异常 RPC_X_ENUM_VALUE_OUT_OF_RANGE。要将对象作为 32 位实体传输,请将 [v1_enum] 属性应用于枚举类型定义。

所以你基本上有两个选项可以在 idl 中使用枚举:1)使用enumwithouttypedef和 2)使用enumwithtypedef并添加v1_enum属性。在第一种情况下,您可以根据需要在方法中声明类型,在第二种情况下,您将不得不使用该类型(因此 v1_enum 属性):

enum MY_ENUM
{
    MY_ENUM_FIRST = 1,
    MY_ENUM_SECOND = 2,
};

typedef [v1_enum] enum
{
    MY_ENUM_TYPE_FIRST = 1,
    MY_ENUM_TYPE_SECOND = 2
} MY_ENUM_TYPE;

[object, uuid(15A7560E-901B-44D2-B841-58620B1A76C5)]
interface IMyInterface : IUnknown
{
    HRESULT MyMethod1(int myParam);
    HRESULT MyMethod2(MY_ENUM_TYPE myParam);
};

像这样使用:

IMyInterface *p = ...;
p->MyMethod1(MY_ENUM_FIRST | MY_ENUM_SECOND);
p->MyMethod2(MY_ENUM_TYPE::MY_ENUM_TYPE_FIRST | MY_ENUM_TYPE::MY_ENUM_TYPE_SECOND);

如果您声明这样的方法:

 HRESULT MyMethod1(enum MY_ENUM myParam);

然后您将使用 16 位枚举(并且您不能在非 typedef 的枚举上添加 v1_enum),所以这不好(除非您对 0-32767 限制没问题)。

注意我还在第二行声明了这一点,以简化 typedef 枚举作为标志转换:

MY_ENUM_TYPE operator | (MY_ENUM_TYPE l, MY_ENUM_TYPE r) { return (MY_ENUM_TYPE)((int)l | (int)r); }

好。typedef 方式对我来说似乎有点矫枉过正,但它具有被键入的优点。如果您在 Windows SDK 中扫描 Microsoft 自己的 .IDL 文件,您会发现它们基本上都使用了这两者……

于 2014-07-29T06:41:15.107 回答