问题描述
我使用的是C + + ATL库。 IDL文件中的方法使用 IQTAction
参数声明,但是当我在.NET中使用这个类型库时,我得到类型为QTAction NOT IQTAction的方法参数:
I'm using a C++ ATL library. Methods in the IDL file are declared with a IQTAction
parameter, but when I use this type library in .NET I get the methods parameters of type 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
{
}
}
为什么?
这是我的头文件和IDL文件:
Here are my header and IDL files:
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 FILE: / p>
IDL FILE:
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;
};
};
推荐答案
据我所知, coclass interface 而不是实际的接口,当它发现只有一个coclass实现该接口作为默认在同一个类型库,并且没有办法阻止它这样做。
As far as I know, the type library importer uses the coclass interface instead of the actual interface when it finds that there's only one coclass implementing that interface as the default within the same type library, and there's no way to prevent it from doing this.
但是,请注意 QTTest
和 IQTTest
都是接口,具有相同的Guid和方法。但是 QTTest
有一个额外的属性, CoClassAttribute(QTTestClass)
,允许Microsoft的C#编译器编译 new QTTest()
into new QTTestClass()
。
However, note that QTTest
and IQTTest
are both interfaces, with the same Guid and methods. But QTTest
has an extra attribute, CoClassAttribute(QTTestClass)
, that allows Microsoft's C# compiler to compile new QTTest()
into new QTTestClass()
.
此tlbimp.exe杂耍使VB6程序员感觉在家,但对于C ++开发人员来说是很奇怪的。在你的情况下,它只意味着在两个等价的接口类型之间转换。
This tlbimp.exe juggling makes VB6 programmers feel at home, but it's quite weird for C++ developers. In your case, it only implies casting between two otherwise equivalent interface types.
这篇关于编译dll使用ATL与方法参数作为接口,但得到他们作为coclasses的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!