如何创建两个从另一个派生的 ATL 接口?

Posted

技术标签:

【中文标题】如何创建两个从另一个派生的 ATL 接口?【英文标题】:how to create two ATL interface derived from another? 【发布时间】:2015-04-19 04:09:28 【问题描述】:

我有一个带有 IDL 接口的 Dll 项目。 我想必须在我的 dll 中连接其中一个可以从另一个派生的接口。 我用 ATL 简单对象向导创建了两个接口。

[
    object,
    uuid(7359AF6C-6E90-4372-991F-556602CB3977),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IZInterface : IDispatch
    [id(1)] HRESULT ZGetStr([out,retval] BSTR* str);
    [id(2)] HRESULT GetSize([in,out] LONG* nSize);
;
[
    object,
    uuid(8CA6DBF2-E402-464D-96AE-3D6642D91E14),
    pointer_default(unique)
]
interface IBClass : IUnknown
    [] HRESULT Method11([out,retval] LONG* l);
;
library DllStandardLib

    importlib("stdole2.tlb");
    [
        uuid(491DF659-012F-4C20-90AA-0CBC5BDE5A68)      
    ]
    coclass ZInterface
    
        [default] interface IZInterface;
    ;
        [
        uuid(43CE897F-17F2-4D45-9098-26B7AEE6EC23)      
    ]
    coclass BClass
    
        [default] interface IBClass;
    ;
;

现在,我在 Class View 中右键单击 CZInterface 然后 Impelement Interface IBClass 。

但在 continer 中,这是一个 C# 项目:

DllStandardLib.ZInterface dd = new DllStandardLib.ZInterface();
dd.Method11();//---> Error: DllStandardLib.ZInterface' does not contain a definition for 'Method11' and no extension method 'Method11' accepting a first argument of type ...

我的项目有什么问题?我希望第二个(派生)接口知道基接口的所有方法和属性。 请帮我!

【问题讨论】:

IBClass 派生自 IUnknown,而不是 IZInterface。所以这当然行不通。 ATL 向导无法帮助您完成此操作,您必须手动完成。也许你不应该。 【参考方案1】:

如果您想实现这一点,最好不要使用对象向导。首先,定义你的接口:

[
    object,
    uuid(7359AF6C-6E90-4372-991F-556602CB3977),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IZInterface : IDispatch

    [id(1)] HRESULT ZGetStr([out,retval] BSTR* str);
    [id(2)] HRESULT GetSize([in,out] LONG* nSize);
;

[
    object,
    uuid(8CA6DBF2-E402-464D-96AE-3D6642D91E14),
    pointer_default(unique)
]
interface IBClass : IZInterface    // IBClass inherits from IZInterface

    [id(3)] HRESULT Method11([out,retval] LONG* l);
;

然后定义实现专用接口的类。在您的库中执行此操作:

library DllStandardLib

    importlib("stdole2.tlb");

    [
        uuid(43CE897F-17F2-4D45-9098-26B7AEE6EC23)      
    ]
    coclass BClass
    
        [default] interface IBClass;
    ;

    // NOTE: No need for ZInterface coclass.
;

请注意,IZInterface 类并不是真正需要的,除非您想提供一个单独的实现(= 另一个类)。

为了使QueryInterface-calls 起作用,您还应该将该接口添加到您的 COM 接口映射中:

class CBClass : 
    // ...

    // ...

BEGIN_COM_MAP(CBClass)
    COM_INTERFACE_ENTRY(IBClass)
    COM_INTERFACE_ENTRY(IZInterface)
END_COM_MAP()

    // ...

    // IBClass-Member
    STDMETHOD(Method11)(LONG* l);    // Implement this in your source file (STDMETHODIMP CBClass::Method11(LONG* l)  return E_NOTIMPL; 

要从 .NET 调用您的 IBClass 接口成员,您必须创建正确类的实例:

DllStandardLib.BClass bc = new DllStandardLib.BClass();
bc.Method11();

【讨论】:

'ATL::CComObject' : 无法实例化抽象类 @nabegheh95:您还必须将Method11-definition 和声明添加到您的课程中;)我也更新了答案! 那我在ZInterface.h和ZInterface.cpp中写什么? @nabegheh95:您不需要它们(如答案中所述)。结果是一个继承树,如下所示:IZInterface -> IBClass -> BClass。对于另一个类 (ZInterface),您将创建一个单独的继承树。 @nabegheh95:运气好吗?

以上是关于如何创建两个从另一个派生的 ATL 接口?的主要内容,如果未能解决你的问题,请参考以下文章

C++:如何前向声明出现在基类的静态方法中的派生类?

ATL(COM) 开发下 -- VS2010

具有派生接口成员的派生接口

C ++:从另一个构造函数隐式调用构造函数

将方法参数类型更改为子类中的派生类

如何确保派生类实现特定方法,保持标准布局?