如何实现给定头文件的接口?

Posted

技术标签:

【中文标题】如何实现给定头文件的接口?【英文标题】:How do I implement an interface given a header file? 【发布时间】:2019-06-13 07:04:01 【问题描述】:

这可能是一个愚蠢的问题,我犹豫了一下,但我是 ATL 的新手。

我需要在我的代码中实现一个接口。我没有那个接口的 TLB 或 IDL,我只有一个头文件。

头文件定义接口如下:

EXTERN_C const IID IID_IExternalCon;
 ...    

     MIDL_INTERFACE("BCAC73A8-0226-4250-9D66-9656AA9BB86C")
        IExternalCon: public IUnknown
        
        public:
            virtual HRESULT STDMETHODCALLTYPE GetName( 
                /* [in] */ __RPC__in ULONG *interface);
           //  ...

        

我需要实现它的多个实例。不幸的是,正在寻找我的接口的加载器没有找到我的这个接口的实现。

我做过这样的事情:

// is this a proper forward reference?
[
    object,
    uuid(BCAC73A8-0226-4250-9D66-9656AA9BB86C), // is this uuid supposed to match the one in the header?
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IExternalCon: IUnknown

;


library ... 
    [
        uuid(d543911a-81b0-4de1-9511-d1f14caceed)
    ]

    // the class implementing my interface
    coclass ExternalConTest
    
        [default] interface IExternalCon;
    ;

任何有关仅基于头文件处理实现接口的帮助、提示或指导将不胜感激。

顺便说一下,我的类定义如下:

class ATL_NO_VTABLE CExternalConTest :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CExternalConTest, &CLSID_ExternalConTest>,
    public IExternalCon

public:
...

BEGIN_COM_MAP(CExternalConTest)
    COM_INTERFACE_ENTRY(IExternalCon)
    COM_INTERFACE_ENTRY(IUnknown)
END_COM_MAP()
..

【问题讨论】:

【参考方案1】:

在 ATL 对象中实现外部接口需要做的是

将该接口添加到已实现接口的列表中(您已经这样做了)。这将修改类二进制布局(vtable 等) 将接口添加到BEGIN_COM_MAP 列表。这将指示底层QueryInterface 实现的ATL 积极回答对该接口ID 的查询(您已经这样做了)。 IUnknown 在这里没有必要。 将接口声明添加到 .h 文件中。链接和注释在那里是可选的,我个人将它们删除。我也总是添加一个带有接口名称的注释,以便我们知道什么接口使用什么方法。当你有很多时,它很有用...... 将接口实现添加到 .cpp 文件中。

所以在您的情况下,.h 文件将是这样的:

class ATL_NO_VTABLE CExternalConTest :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CExternalConTest, &CLSID_ExternalConTest>,
    public IExternalCon // change the class layout

public:
...

BEGIN_COM_MAP(CExternalConTest)
    COM_INTERFACE_ENTRY(IExternalCon) // answer to QueryInterface calls
END_COM_MAP()
...

public:
    // IExternalCon
    HRESULT GetName(ULONG *interface);
...
    // IWhatever
    HRESULT Blabla( ... );
    HRESULT Blabla2( ... );

...

.cpp 文件:

// CExternalConTest
...
// IExternalCon
HRESULT CExternalConTest::GetName(ULONG *interface)

    // TODO : implement this
    return S_OK;

...
// IWhatever
HRESULT CExternalConTest::Blabla(...)

    // TODO : implement this
    return S_OK;


HRESULT CExternalConTest::Blabla2(...)

    // TODO : implement this
    return S_OK;

关于 .idl,您无需执行任何操作,因为 Visual Studio 使用它作为代码生成的基础。通常,在使用 Visual Studio 时,您首先更改 .idl(是否使用向导),然后填补空白。

【讨论】:

以上是关于如何实现给定头文件的接口?的主要内容,如果未能解决你的问题,请参考以下文章

http请求如何修改请求头?

如何找到实现给定接口的所有类?

C程序如何调用C++接口?

C语言中的接口如何实现?它和函数的定义有什么区别,请C高手来指导,杜绝Java的接口和类的回答因为我精通JAVA

C#如何确定一个类型是不是实现了给定的接口?

如何在 C# 中编写实现给定接口的通用容器类?