使用 ATL 编译 dll,将方法参数作为接口,但将它们作为 coclasses
Posted
技术标签:
【中文标题】使用 ATL 编译 dll,将方法参数作为接口,但将它们作为 coclasses【英文标题】:Compile dll using ATL with method parameter as Interfaces, but get them as coclasses 【发布时间】:2015-06-29 05:38:00 【问题描述】:我正在使用 C++ ATL 库。 IDL 文件中的方法是用 IQTAction
参数声明的,但是当我在 .NET 中使用这个类型库时,我得到了 QTAction NOT IQTAction 类型的方法参数:
namespace COMTest3Lib
[ClassInterface(0)]
[Guid("C6DD8D8E-8375-4CA6-8534-007776D96215")]
[TypeLibType(2)]
public class QTTestClass : IQTTest, QTTest
public QTTestClass();
public virtual void GetActiveAction(out QTAction pActionOut);
public virtual void RunAction(QTAction pActionIn);
namespace COMTest3Lib
[CoClass(typeof(QTActionClass))]
[Guid("FBCC87D9-4E5C-40D2-853F-E8548E625C5B")]
public interface QTAction : IQTAction
这是为什么呢?如何让它使用接口而不是 coclass 作为参数的类型?
这是我的头文件和 IDL 文件:
using namespace ATL;
//QTTest.h
class ATL_NO_VTABLE CQTTest :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CQTTest, &CLSID_QTTest>,
public IDispatchImpl<IQTTest, &IID_IQTTest, &LIBID_COMTest3Lib, /*wMajor =*/ 1, /*wMinor =*/ 0>
public:
CQTTest()
m_pActiveAction.CoCreateInstance(CLSID_QTAction); //construct an action;
DECLARE_REGISTRY_RESOURCEID(IDR_QTTEST)
BEGIN_COM_MAP(CQTTest)
COM_INTERFACE_ENTRY(IQTTest)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
return S_OK;
void FinalRelease()
::MessageBox(NULL, L"#################QTTest is being disposed", L"info", 0);
public:
STDMETHOD(GetActiveAction)(/*out*/IQTAction** pActionOut);
STDMETHOD(RunAction)(/*in*/IQTAction* pActionIn);
private:
CComPtr<IQTAction> m_pActiveAction;
;
OBJECT_ENTRY_AUTO(__uuidof(QTTest), CQTTest)
IDL 文件:
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(FBCC87D9-4E5C-40D2-853F-E8548E625C5B),
pointer_default(unique)
]
interface IQTAction : IDispatch
[helpstring("method Run")] HRESULT Run(void);
;
[
object,
uuid(19F205D2-1D1C-4DB7-A731-498665CC297F),
version(1.0)
]
interface IQTTest : IDispatch
[helpstring("method GetActiveAction")] HRESULT GetActiveAction([out] IQTAction** pActionOut);
//[helpstring("method Run")] HRESULT Run(void);
[helpstring("Run a specific action")] HRESULT RunAction([in] IQTAction* pActionIn);
;
[
uuid(0E651E25-832E-4410-9A9E-F8CD8574F4D8),
]
library COMTest3Lib
importlib("stdole2.tlb");
[
uuid(C6DD8D8E-8375-4CA6-8534-007776D96215)
]
coclass QTTest
[default] interface IQTTest;
;
[
uuid(72D899CC-7722-4260-A441-3D1225132019)
]
coclass QTAction
[default] interface IQTAction;
;
;
【问题讨论】:
为什么反对票和接近票?如果您不了解操作,请向他询问详细信息。对我来说,很清楚要问什么:为什么在IQTTest
的方法中使用QTAction
.NET 类类型而不是IQTAction
.NET 接口类型?
IQTAction
仅由类型库中的 QTAction 实现。 .NET 互操作看到它并“合并”试图简化事情的定义。尽管如此,您在 .NET 端将其视为QTAction
,它仍然是IQTAction
接口。
【参考方案1】:
据我所知,类型库导入器使用 coclass interface 而不是实际接口时,它发现只有一个 coclass 实现该接口作为同一类型库中的默认接口,并且没有办法阻止它这样做。
但是,请注意QTTest
和IQTTest
都是接口,具有相同的 Guid 和方法。但是QTTest
有一个额外的属性CoClassAttribute(QTTestClass)
,它允许微软的C# 编译器将new QTTest()
编译成new QTTestClass()
。
这种 tlbimp.exe 杂耍让 VB6 程序员有宾至如归的感觉,但对于 C++ 开发人员来说却很奇怪。在您的情况下,它仅意味着在两个其他等效接口类型之间进行转换。
【讨论】:
我想指出的是,TLBIMP.exe 也不会生成QTTest
(coclass 接口),当它与实现它的coclass 不在同一个类型库中时,它会生成原始接口( IQTTest
)。
感谢您的注意,我相应地编辑了答案。以上是关于使用 ATL 编译 dll,将方法参数作为接口,但将它们作为 coclasses的主要内容,如果未能解决你的问题,请参考以下文章
在构建导出包含ATL :: CString成员的类的DLL时发出警告C4251