在COM IDL中如何从COM依赖项引用枚举?

时间:2015-09-04 14:00:18

标签: c++ enums com idl

我正在使用ATL创建进程内COM服务器。此COM服务器将公开的类型是枚举。需要使用此COM服务器所依赖的另一个COM服务器的值来定义此枚举的值。我已经尝试了几乎所有我能想到的东西,让它完全没有取得真正的成功。

这是COM服务器依赖项的IDL。

Type1Lib.idl

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

[
    uuid(B777544C-77D9-4417-8302-4EAC8272DEDC),
    version(1.0),
]
library Type1Lib
{
   // required system import.
   importlib("stdole2.tlb");

   // A simple enum to be used by another COM server.
   typedef
   [
      uuid(EF82F7A5-3A55-44B9-AD06-201A6D0A6021)
   ]
   enum Enum1
   {
      One,
      Two,
      Three,
      Four,
      Five
   } Enum1;
};

以下是尝试使用Enum1的COM服务器依赖的IDL(包括我尝试过的一些方法)。

Type2Lib.idl

// Required system imports.
import "oaidl.idl";
import "ocidl.idl";

// (2) FAIL Enables use of Type1Lib enums in this idl file but only as long as usage
// of those types is totally unqualified. The problem with that is that when a tlh file
// is generated from the type library this idl file creates, that tlh file is malformed
// because the unqualified enum references do not resolve to anything.
import "Type1Lib.idl";

// FAIL Neither of these statements even compiles, Emits error:
// "Native Compiler support only available in C++ compiler".
// The tlh is C++ and apparently cannot be parsed by MIDL.
//import "type1lib.tlh";
//#include "type1lib.tlh"

[
    uuid(D40AC182-8744-42D1-B194-602AEDDC6E7C),
    version(1.0),
]
library Type2Lib
{
   // Required system import.
    importlib("stdole2.tlb");

   // Import Type1Lib without redeclaring the types it contains.
   // (1) FAIL Enables usage of the enum type in Type1Lib, but not the enum values,
   // so that's utterly useless.
//   importlib("Type1Lib.dll");

   typedef
   [
      uuid("0B8D400A-6A8F-44B3-986D-9E099830BB6D")
   ]
   enum Enum2
   {
      A = 0x80000000 + One, // One references an enum value from Type1Lib.
      B,
      C,
      D,
      E
   } Enum2;


   [
       object,
       uuid(F5BA0CB0-B7C7-4483-A3D9-D4B9E39E6269),
       dual,
       nonextensible,
       pointer_default(unique)
   ]
   interface IType2 : IDispatch
   {
      [id(1)] HRESULT Method1([out,retval] LONG* retVal);

      // Partial success. Can reference typedef'ed enum using importlib. Cannot however access the enum values.
      [id(2)] HRESULT Method2([in] enum Enum1 arg1);
   };

    [
        uuid(6179272F-4B34-4EF0-926B-296D3AA73DB7)      
    ]
    dispinterface _IType2Events
    {
        properties:
        methods:
    };

    [
        uuid(75CE545A-D2DA-4EC9-80CF-37531516DFC1)      
    ]
    coclass Type2
    {
        [default] interface IType2;
        [default, source] dispinterface _IType2Events;
    };
};

因此,在类型库(嵌入在dll中)中使用importlib不起作用,因为它不允许访问Enum1的值。

导入Type1Lib.idl并不是很有效,因为虽然枚举值可用但它们只能以非限定形式使用,所以虽然现在可以编译Type2Lib.idl,但是当dllmain中包含Type2Lib_i.h时.cpp枚举值不能解析为任何东西。另一个问题是导入" Type1Lib.idl"声明导致添加" #include" Type1Lib.h""在Type2Lib_i.h中的行,文件Type1lib.h不存在,并且没有理由应该存在。

这两个问题都有解决方法,但它们并不能真正产生可行的解决方案。

在stdafx.h中导入带有no_namespace的Type1Lib将解决无法解析的不合格枚举的问题,但现在你正在打开你无法解决的typename冲突的可能性,因为现在你无法解决使用命名空间。

在stdafx.h中导入Type1Lib之前,您可以使用#pragma include_alias重定向#include" Type1Lib.h"从不存在的标题到例如

的标题
#pragma include_alias("Type1Lib.h", "windows.h")
#import <Type1Lib.dll> no_namespace

现在一切都在建立。问题是你现在有几个令人讨厌和脆弱的变通方法等待搞砸一切,还有一个其他明显的问题,我还没有提到这是什么。如果您通过&#39; importlib&#39;引用您的COM依赖项?然后你就可以得到一个引用到你的依赖项,你的IDL文件可以使用引用的类型库中的类型,但你不会重新定义任何东西。但是,如果您使用&#39; import&#39;导入idl文件?那么你基本上拥有的是一个&#39; include&#39;调整用于IDL文件。这个问题是使用&#39; import&#39;将导致在您的依赖IDL文件中创建依赖项IDL文件中的类型的重复项,这是您绝对不需要的。

所以我完全失败了。我想做的事情似乎很简单,尽管我尝试了所有我能想到的东西,但我只看到了错误。我迫切需要一些COM大师让我走上一条有用的道路。

0 个答案:

没有答案