如何实现给定头文件的接口?
How do I implement an interface given a header file?
这可能是一个愚蠢的问题,我犹豫了 post,但我是 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定义如下:
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()
..
}
要在 ATL 对象中实现外部接口,您需要做的是
- 将接口添加到已实现接口的列表中(你这样做了)。这将修改 class 二进制布局(vtable 等)
- 将接口添加到
BEGIN_COM_MAP
列表。这将指示 ATL 底层 QueryInterface
实现对针对该接口 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(使用或不使用向导),然后填补空白。
这可能是一个愚蠢的问题,我犹豫了 post,但我是 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定义如下:
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()
..
}
要在 ATL 对象中实现外部接口,您需要做的是
- 将接口添加到已实现接口的列表中(你这样做了)。这将修改 class 二进制布局(vtable 等)
- 将接口添加到
BEGIN_COM_MAP
列表。这将指示 ATL 底层QueryInterface
实现对针对该接口 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(使用或不使用向导),然后填补空白。