如何定义COM coclass的实现?

6

我是COM的新手,我在互联网上找到了如何在C++中创建一个COM类(以被C#使用)。我发现在.idl文件中,我必须像这样填写:

[
object,
uuid(a93164ee-e6d4-44be-aa27-f00ce6972719),
helpstring("interface ITopologyQuery")
]

interface ITopologyQuery : IUnknown
{
  HRESULT LoadFile(BSTR completeFileName);

  HRESULT SetParameters(int above, int percentage);
}

[
  uuid(a958f2af-8b55-43c4-9fc3-c39d83fc1376)
]
library TopologyQueryLib
{
  [
    uuid(cc814992-31ec-4a1f-a41e-111ade27bdfe),
    helpstring("TopologyQuery class")
  ]
  coclass CTopologyQuery
  {
    [default] interface ITopologyQuery;
  };
}

现在我的问题是,你在哪里定义CTopologyQuery类?如果我把它定义为另一个文件中的普通C++类,编译器会正确地将我的类与接口链接起来吗?这个C++类的代码如下(它是在.cpp文件中实现的):
class CTopologyQuery : public ITopologyQuery
{
  public:

    __stdcall CTopologyQuery();

    //IUnknown interface 
    HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
    ULONG   __stdcall AddRef();
    ULONG   __stdcall Release();

    //ITopologyQuery interface
    HRESULT __stdcall LoadTopologyFile(BSTR completeFileName);
    HRESULT __stdcall SetParameters(int above, int percentage);

  private:
};

现在,如果我将库部分放入.idl文件中或不放入,它都可以编译。我有点迷失于此,不知道应该怎么做?我知道coclass定义应该为接口提供默认实现,但对我来说看起来像一个没有方法的空类...


1
你有读过《将COM组件公开给.NET Framework》吗?这篇文章在我学习 .Net / COM 互操作时帮了我很多忙。 - Justin
你使用 ATL 吗?MFC?还是全部手动实现? - bdonlan
1
@bdonlan:我正在使用MFC,但我想使用ATL,但向导对我不起作用(由于某种不明原因,当它启动时,它会清除我的资源附加包含目录,然后给我一个RC1015错误)。因此,我正在尝试手动操作(同时我也在尝试理解COM的工作原理)。 - Carl
好的。这是一个EXE还是DLL? - bdonlan
此外,对于 DLL,这是一个进程内还是进程外的服务器? - bdonlan
@bdonlan:这是一个EXE文件。我知道它不够干净,但由于有一大堆遗留代码,我想要一个带有隐藏GUI的MFC应用程序,可以公开COM对象。 - Carl
1个回答

6

IDL(接口定义语言)部分以一种与语言无关的方式定义了二进制接口,其看起来很像C++。

通常用于构建二进制类型库,这是一个包含有关您的COM类信息的DLL。您可以使用Microsoft的COM / OLE Viewer浏览现有的类型库。

对于C ++使用您的非IDispatch COM类,您不需要该类的信息,因为C ++编译器所需了解的所有信息(至少)都在您的C ++头文件中。

但是,从IDL描述和生成的类型库中生成的粘合代码有助于从C#和其他语言使用您的COM类。我记得它还可以帮助生成使用CoCreateInstance和朋友使用您的COM类所需的Windows注册表键和值。因此,它是一种基础设施机械,支持您的COM类的语言无关视图和使用,可以说是支持语言无关视图和使用的基础设施机械。

祝好!


我仍然不明白编译器和COM接口的用户(在这种情况下是ITopologyQuery)如何知道必须创建CTopologyQuery的实例。而且,.idl文件中的“library TopologyQueryLib {...}”块是否必要或无用? - Carl
2
@Carl:即使在COM中也没有什么魔法。实例化COM对象的通常方法是调用CoCreateInstance,给它一个类的128位CLSID(这是UUID)和一个接口的128位IID(这是UUID),该类必须提供该接口。它在注册表中查找该CLSID,以获取服务器、DLL或EXE。然后它请求该服务器提供一个实例。它要求该实例提供接口。我对EXE服务器的实例化方式有点模糊,这是你的情况。但是,对于DLL,它是由DLL提供的简单对象工厂(众所周知的函数)。干杯! - Cheers and hth. - Alf
@Carl(续)……换句话说,COM接口的用户可以通过创建实现该接口的类的实例来获取该接口的提供程序。许多类都可以实现一个接口(例如,所有类都实现IUknown)。这就是IDL中类定义的目的:它用于通知用户至少有一个实现了该接口的类存在。 - Cheers and hth. - Alf
好的,这解释了一些事情,谢谢。我会进行一些测试,以帮助我更好地理解事物是如何工作的。 - Carl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接