如何在 COM 服务器中使用用户定义类型 (UDT)?

发布于 2024-07-18 07:38:40 字数 1641 浏览 3 评论 0原文

我有一个 COM 服务器,其方法当前返回一个整数:

[
    object,
    uuid("..."),
    dual,
    helpstring("IMyCOMServer Interface"),
    pointer_default(unique)
]
__interface IMyCOMServer : IDispatch
{
    [id(1), helpstring("method MyQuery")]
    HRESULT MyQuery([in] BSTR instr, [out,retval] int* outint);
};

这编译得很好,但我宁愿返回一个枚举:(此代码实际上位于接口定义之上)

typedef
[
    uuid("..."),
    v1_enum,
    helpstring("Enum")
]
enum {
    value_a,
    value_b,
    value_c
} MyEnum;

再次编译得很好是的,但是一旦我在接口和实现中将 int* 更改为 MyEnum*,我就会收到链接器错误:

[id(1), helpstring("method MyQuery")]
HRESULT MyQuery([in] BSTR instr, [out,retval] MyEnum* outint);

error MIDL2025 : syntax error : expecting a type specification near "MyEnum"

无论我采用哪种方式,我都无法得到它来编译。


感谢 Euro Micelli 事实证明,真正的问题是我的用户定义类型(枚举)不是将其放入生成的 .IDL 文件中。 从网上论坛查询来看,这似乎是一个常见问题。

博客文章 Star Tech:UDT (用户定义类型)和 COM 引导我走上了正确的道路。 使用属性 ATL 时似乎需要一种解决方法。

总之,我进行了以下更改:

创建了 udt.idl:

import "oaidl.idl";
import "ocidl.idl";

[
    uuid("..."),
    v1_enum,
    helpstring("Enum")
]
typedef enum MyEnum {
    value_a,
    value_b,
    value_c
} MyEnum_t;

[
    version(1.0),
    uuid(...),
    helpstring(...)
]
library MyLibrary
{
    enum MyEnum;
}

在主 .cpp 文件中的模块属性之前添加了以下行,以便导入上述 IDL进入生成的文件:

[importidl("udt.idl")];

I have a COM server with a method currently returning an integer:

[
    object,
    uuid("..."),
    dual,
    helpstring("IMyCOMServer Interface"),
    pointer_default(unique)
]
__interface IMyCOMServer : IDispatch
{
    [id(1), helpstring("method MyQuery")]
    HRESULT MyQuery([in] BSTR instr, [out,retval] int* outint);
};

This compiles fine, but I'd rather return an enum: (this code is actually above the interface definition)

typedef
[
    uuid("..."),
    v1_enum,
    helpstring("Enum")
]
enum {
    value_a,
    value_b,
    value_c
} MyEnum;

Which again compile fine of its own right, but as soon as I change the int* to MyEnum* in the interface and implementation, I get linker errors:

[id(1), helpstring("method MyQuery")]
HRESULT MyQuery([in] BSTR instr, [out,retval] MyEnum* outint);

error MIDL2025 : syntax error : expecting a type specification near "MyEnum"

Whichever way I do it, I can't get it to compile.


Thanks to Euro Micelli it turns out that the real problem is that my User Defined Type (the enum) wasn't making it into the generated .IDL file. Judging by forum queries online, this seems to be a common problem.

A blog article Star Tech: UDT (User Defined Types) and COM guided me down the right path. It seems that a workaround is needed when using attributed ATL.

In summary, I made the following changes:

Created udt.idl:

import "oaidl.idl";
import "ocidl.idl";

[
    uuid("..."),
    v1_enum,
    helpstring("Enum")
]
typedef enum MyEnum {
    value_a,
    value_b,
    value_c
} MyEnum_t;

[
    version(1.0),
    uuid(...),
    helpstring(...)
]
library MyLibrary
{
    enum MyEnum;
}

Added the following line prior to the module attribute in the main .cpp file so that the above IDL gets imported into the generated file:

[importidl("udt.idl")];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我爱人 2024-07-25 07:38:40

(这是根据实际的 IDL 改编的,所以我知道它有效)

[uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), v1_enum, helpstring("Enum")]
enum MyEnum {
    value_a,
    value_b,
    value_c
} ;

另外,在您的“库”部分中,您还必须包含枚举,否则枚举将不会导出到类型库:

library MyLib
{
    enum MyEnum;
...
};

(This is adapted from an actual IDL, so I know it works)

[uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), v1_enum, helpstring("Enum")]
enum MyEnum {
    value_a,
    value_b,
    value_c
} ;

Plus, in your Library section you must include the enum as well, or the enum won't be exported to the type library:

library MyLib
{
    enum MyEnum;
...
};
ι不睡觉的鱼゛ 2024-07-25 07:38:40

这非常依赖于编译器,因为枚举没有固定的存储大小。

还有兼容性角度 - 如何在 Visual Basic 或 C# 中表示该枚举? 底层存储类似于整数,所以这就是 COM 所允许的。

This is very compiler-dependent, since enums don't have a fixed storage size.

There's also the compatibility angle - how would you represent that enum in, say, Visual Basic, or C#? The underlying storage is something like an integer, so that's what COM allows.

云胡 2024-07-25 07:38:40

您已经差不多明白了,但是 idl 编译器的语法比 cl.exe 稍微严格一些。 您需要在枚举之前有初始枚举名称,如下所示。

typedef
[uuid("..."), v1_enum, helpstring("Enum")]
enum tagMyEnum
{
    value_a,
    value_b,
    value_c
} MyEnum;

如果您构建并注册了 tlb,那么脚本语言应该能够在脚本和 .NET 中访问您的枚举。

You've almost got it, but the idl compiler has a little stricter syntax than the cl.exe. You need to have the initial enum name before the enum like this.

typedef
[uuid("..."), v1_enum, helpstring("Enum")]
enum tagMyEnum
{
    value_a,
    value_b,
    value_c
} MyEnum;

If you build and register your tlb then scripting languages should be able to access your enum in scripts and .NET.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文