COM是否支持多个双接口?

时间:2014-05-06 06:25:16

标签: com c++builder idispatch

我创建了一个具有多个双接口的COM对象。它适用于早期版本的编译器,但不适用于当前版本。

我的问题:COM规范是否说这应该有用(因此我应该报告一个编译器错误),或者不打算工作? This page表明也许它不适合工作。

RIDL文件:

[
  uuid(0A6CC6CE-623E-4455-8B9B-65178FB7585A),
  version(1.0),
  helpstring("Library to illustrate failure of Dispatch interface")
]
library DaxFail
{

  importlib("stdole2.tlb");

  interface IFoo;
  coclass DaxFailClass;
  interface IBar;


  [
    uuid(2CD15FFC-0C09-4A29-BD57-99BBC53AE01F),
    helpstring("Dispatch interface for DaxFailClass Object"),
    dual,
    oleautomation
  ]
  interface IFoo: IDispatch
  {
    [id(0x000000C9)]
    HRESULT _stdcall foo_method(void);
  };

  [
    uuid(AECB5DF3-EDE3-441A-93E6-220CB271AD43),
    dual,
    oleautomation
  ]
  interface IBar: IDispatch
  {
    [id(0x000000C9)]
    HRESULT _stdcall bar_method(void);
  };

  [
    uuid(9DCD1024-6E1A-435E-82F9-FD4FE863D710),
    helpstring("DaxFailClass Object")
  ]
  coclass DaxFailClass
  {
    [default] interface IFoo;
    interface IBar;
  };

};

访问它的代码(这是伪代码,我在“真实”代码中有额外的语句来显示HRESULT s):

const GUID CLSID_DaxFailClass = {0x9DCD1024, 0x6E1A, 0x435E,{ 0x82, 0xF9, 0xFD,0x4F, 0xE8, 0x63,0xD7, 0x10} };
const GUID IID_IFoo = {0x2CD15FFC, 0x0C09, 0x4A29,{ 0xBD, 0x57, 0x99,0xBB, 0xC5, 0x3A,0xE0,     0x1F} };
const GUID IID_IBar = {0xAECB5DF3, 0xEDE3, 0x441A,{ 0x93, 0xE6, 0x22,0x0C, 0xB2, 0x71,0xAD, 0x43} };

int _tmain()
{
    IDispatch *intf, *ibar;
    HRESULT hr;
    DISPID disp_id;
    wchar_t *name;

    CoInitialize(NULL);

    hr = CoCreateInstance(CLSID_DaxFailClass, 0, CLSCTX_ALL, IID_IDispatch, (void **)&intf);

// This returns 0 , and doing Invoke with disp_id executes foo_method
    name = L"foo_method";
    intf->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &disp_id );

// returns 0
    hr = intf->QueryInterface(IID_IBar, (void **)&ibar);

// this returns 0x80020006
    name = L"bar_method";
    hr = ibar->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &disp_id );

// This returns 0 , and doing Invoke with disp_id executes foo_method
    name = L"foo_method";
    hr = ibar->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &disp_id );

    CoUninitialize();
    getchar();
}

因此,问题是ibar的行为与intf完全相同。 ibar可以foo_method调用它,但似乎不知道bar_method是什么。

我希望第二次GetIDsOfNames调用0,然后调用才能调用bar_method,第三个GetIDsOfNames应该0x80020006

关于编译器的额外信息(虽然,很明显,我的问题是COM规范是否应该工作):在BDS 2006中工作并且在C ++ Builder XE5中不起作用。我在XE5中编写了实现COM的代码,ojbect工厂在首次创建对象时使用ITypeInfo *填充GetTypeInfoOfGUID(CLSID_....),但QueryInterface的实现仅使用相同的ITypeInfo { {1}}对于所有结果,它不会再使用新的GetTypeInfoOfGUID调用IID。在ITypeInfo的实施中DispGetIDsOfNames传递给IDispatch::GetIDsOfNames

1 个答案:

答案 0 :(得分:2)

规范不必对此说些什么。

  1. 您必须在一个类上使用不同的接口。这是允许的。
  2. 两者都来自IDispatch。这也是允许的。
  3. 两者都必须自己实施,这项实施应该发挥作用。
  4. 如果您的双界面出现问题" usally" IDL编译器会告诉你。

    这里有你的代码:如果没有看到接口的类实现,我什么都不能说。 是的:它有效,您可以在CodeProject

    找到ATL的样本

    这正是你正在做的事情以及更多。