“能不能?”;“枚举”;是否用于COM中的标志?

“能不能?”;“枚举”;是否用于COM中的标志?,com,enums,idl,midl,Com,Enums,Idl,Midl,在COM对象的IDL中,我执行以下操作: enum TxMyFlags { , flagOption = 1, , flagOtherOption = 2, , flagMoreOption = 4, , flagAnotherFlag = 8, , flagExtra = 128 // etc. }; 并具有可以获取标志的和(或按位或相同内容)的函数,例如(在IDL中) 预期用途示例如下: a_method( flagExtra | flagMoreOption

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

enum TxMyFlags
{
,    flagOption = 1,
,    flagOtherOption = 2,
,    flagMoreOption = 4,
,    flagAnotherFlag = 8,
,    flagExtra = 128
// etc.
};
并具有可以获取标志的和(或按位或相同内容)的函数,例如(在IDL中)

预期用途示例如下:

a_method( flagExtra | flagMoreOption );

它似乎可以工作,但这实际上是允许的,还是RPC传输或其他可能会拒绝不完全在枚举定义中的枚举参数值?

如果您的客户端和服务器正在处理中(并且没有真正的mashaling发生,没有涉及RPC),您将不会看到任何问题,无论您如何定义它,它都将被视为其int/long/which整数类型,大小相当

因此,进程外(或跨单元编组)的情况可能是一个问题。在这种情况下,如以下文件所述:(以及您的评论):

enum类型的对象是int类型,其大小为 依赖于系统。默认情况下,枚举类型的对象被视为 通过网络传输时,类型为unsigned short的16位对象。 超出范围0-32767的值会导致运行时异常 RPC_X_枚举值超出范围。要将对象作为32位实体传输, 将[v1_enum]属性应用于enum typedef

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

这样使用:

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);
如果您声明这样的方法:

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'd枚举上添加v1_枚举),因此这并不好(除非您同意0-32767限制)

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

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

嗯。typedef方式对我来说似乎有点过分,但它有被输入的优点。如果您在Windows SDK中扫描Microsof自己的.IDL文件,您将看到它们基本上同时使用…

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

因此,进程外(或跨单元编组)的情况可能是一个问题。在这种情况下,如以下文件所述:(以及您的评论):

enum类型的对象是int类型,其大小为 依赖于系统。默认情况下,枚举类型的对象被视为 通过网络传输时,类型为unsigned short的16位对象。 超出范围0-32767的值会导致运行时异常 RPC_X_枚举值超出范围。要将对象作为32位实体传输, 将[v1_enum]属性应用于enum typedef

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

这样使用:

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);
如果您声明这样的方法:

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'd枚举上添加v1_枚举),因此这并不好(除非您同意0-32767限制)

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

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

嗯。typedef方式对我来说似乎有点过分,但它有被输入的优点。如果你在Windows SDK中扫描微软自己的.IDL文件,你会发现它们基本上都使用了…

当然,枚举在COM中得到了很好的支持。没有什么比在互操作中将一个类型从一个映射到另一个类型更有效的了。@HansPassant我特别想问的是,COM方法的
enum
type参数是否可以有一个不是enum成员之一的整数值(例如,在我的示例中是
132
)当然,整数映射到枚举。从IDL中应该很明显。你一直在寻找不存在的问题,不知道问题的关键是什么。启发我们。我不认为这是“从IDL中显而易见的”。此外,MIDL文档指出,不带
v1_enum
标记的枚举的最大值为65535,因此
int
映射到枚举的情况不可能是真的。关于“不存在的问题”,仅仅因为某些东西现在似乎可以工作,并不意味着它可以保证工作。(例如,我使用了一个
long
作为
[可选]
参数多年,没有出现任何问题,直到发现它实际上不受支持,并且某个特定的语言绑定遇到了问题)。当然,枚举在COM中得到了很好的支持。没有什么比在互操作中将一个类型从一个映射到另一个类型更有效的了。@HansPassant我特别想问的是,COM方法的
enum
type参数是否可以有一个不是enum成员之一的整数值(例如,在我的示例中是
132
)当然,整数映射到枚举。从IDL中应该很明显。你一直在寻找不存在的问题,不知道问题的关键是什么。启发我们。我不认为这是“从IDL中显而易见的”。此外,MIDL文档指出,不带
v1_enum
标记的枚举的最大值为65535,因此
int
映射到枚举的情况不可能是真的。关于“不存在的问题”,仅仅因为某些东西现在似乎可以工作,并不意味着它可以保证工作。(例如,我使用了一个
long
作为
[可选]
参数多年,一直没有问题,直到发现它实际上不受支持,并且某个特定的语言绑定遇到问题)。谢谢,回答得好。
运算符