【发布时间】:2020-03-02 07:06:12
【问题描述】:
我正在尝试在 Eclipse C++ 环境(MinGW GCC 工具链)中调用已注册的 COM 接口(Inproc dll)。因此,我不相信我可以像在 Visual C++ 中通常那样简单地导入 dll 类型库。我正在尝试自己定义接口以简化函数调用,而不是使用 Invoke。
oleview 外接口的 IDL 如下所示:
uuid(9293C753-B073-11D2-BD89-0060978EEB9C),
helpstring("IXSequence Interface"),
dual
]
dispinterface IXSequence {
properties:
methods:
[id(0x00000001), helpstring("method Close")]
void Close();
[id(0x00000002), helpstring("method New")]
void New();
[id(0x00000003), helpstring("method Open")]
void Open(
BSTR FileName,
long ReadOnly);
[id(0x00000004), helpstring("method Save")]
void Save(
BSTR UserName,
BSTR Comment,
long Overwrite);
[id(0x00000005), helpstring("method SaveAs")]
void SaveAs(
BSTR FileName,
BSTR UserName,
BSTR Comment,
long Overwrite);
[id(0x00000006), propget, helpstring("property Header")]
VARIANT Header();
[id(0x00000007), propget, helpstring("property AuditDataCollection")]
VARIANT AuditDataCollection();
[id(0x00000008), propget, helpstring("property Samples")]
VARIANT Samples();
[id(0x00000009), propget, helpstring("property BracketType")]
XBracketTypes BracketType();
[id(0x00000009), propput, helpstring("property BracketType")]
void BracketType([in] XBracketTypes rhs);
[id(0x0000000a), propget, helpstring("property UserLabel")]
BSTR UserLabel(short Index);
[id(0x0000000a), propput, helpstring("property UserLabel")]
void UserLabel(
short Index,
[in] BSTR rhs);
[id(0x0000000b), propget, helpstring("property TrayConfiguration")]
BSTR TrayConfiguration();
[id(0x0000000b), propput, helpstring("property TrayConfiguration")]
void TrayConfiguration([in] BSTR rhs);
[id(0x0000000c), propget, helpstring("property FileName")]
BSTR FileName();
[id(0x0000000d), propget, helpstring("property NewFile")]
long NewFile();
};
我尝试在自己的头文件中定义接口,如下所示:
const GUID CLSID_XcalFiles = { 0x9293C754, 0xB073, 0x11D2, {0xBD, 0x89, 0x00, 0x60, 0x97, 0x8E, 0xEB, 0x9C } };
const IID IID_IXSequence = { 0x9293C753, 0xB073, 0x11D2, {0xBD, 0x89, 0x00, 0x60, 0x97, 0x8E, 0xEB, 0x9C } };
typedef enum {
XUnspecified = 0,
XOverlapped = 1,
XNonBracketed = 2,
XNonOverlapped = 3,
XOpen = 4
} XBracketTypes;
enum XSampleTypes
{
XSampleUnknown = 0,
XSampleBlank = 1,
XSampleQC = 2,
XSampleStdClear = 3,
XSampleStdUpdate = 4,
XSampleStdBracket = 5,
XSampleStdBracketStart = 6,
XSampleStdBracketEnd = 7,
XSampleProgram = 8,
XSampleNumbersOfDifferentTypes = 9
};
DECLARE_INTERFACE_(IXSequence, IDispatch)
{
//methods
STDMETHOD_(void, Close)(THIS)PURE;
STDMETHOD_(void, New)(THIS)PURE;
STDMETHOD_(void, Open)(THIS_ BSTR FileName, long ReadOnly)PURE;
STDMETHOD_(void, Save)(THIS_ BSTR UserName, BSTR Comment, long Overwrite)PURE;
STDMETHOD_(void, SaveAs)(THIS_ BSTR FileName, BSTR UserName, BSTR Comment, long Overwrite)PURE;
STDMETHOD_(VARIANT, GetHeader)(THIS)PURE;
STDMETHOD_(VARIANT, GetAuditDataCollection)(THIS)PURE;
STDMETHOD_(VARIANT, GetSamples)(THIS)PURE;
//properties
STDMETHOD_(XBracketTypes, BracketType)(THIS)PURE;
STDMETHOD_(void, BracketType)(THIS_ XBracketTypes rhs)PURE;
STDMETHOD_(BSTR, UserLabel)(THIS_ short Index)PURE;
STDMETHOD_(void, UserLabel)(THIS_ short Index, BSTR rhs)PURE;
STDMETHOD_(BSTR, TrayConfiguration)(THIS)PURE;
STDMETHOD_(void, TrayConfiguration)(THIS_ BSTR rhs)PURE;
STDMETHOD_(BSTR, FileName)(THIS)PURE;
STDMETHOD_(long, NewFile)(THIS)PURE;
};
这似乎适用于方法调用,但不适用于属性。当我尝试调用任何属性函数时,我会遇到访问冲突。但是,如果我使用类似的东西,它似乎确实有效
STDMETHOD(GetBracketType)(THIS_ XBracketTypes* rhs)PURE;
这有意义吗?有没有更好的方法来声明 COM 接口的属性,以便我可以像使用普通属性一样使用它们?
【问题讨论】:
-
COM 属性由“普通”方法支持,一个 getter 和一个 setter。一些客户端(例如脚本语言)可以在这些方法调用周围包装语法糖,使它们看起来像真正的属性,但这都是一种错觉。底层方法确实看起来像你展示的那样;你在正确的轨道上。
-
现在,你不能用 MIDL 编译器编译你的 IDL 吗?它的输出之一是一个看起来与您正在手工制作的文件非常相似的 .h 文件。
-
@IgorTandetnik 脚本语言通常通过
IDispatch::GetIDsOfNames()和IDispatch::Invoke(),它们不直接访问属性getter/setter 方法。所以,当一个脚本访问obj.Prop或调用obj.Method()时,实际上是调用obj.GetIDsOfNames()获取Prop或Method的DispID(如果找不到DispID则报错)然后调用obj.Invoke()根据需要使用该 DispID 以及适当的标志和参数。 -
我会提示,如果您要从 C++ 调用,请查看接口输出,而不是 OLEVIEW 中的调度接口输出。接口将分为dispinterface和interface,但是你要在interface部分使用ins。
-
老兄。它是一个调度接口,这意味着客户端需要通过 IDispatch 调用这些成员。当您忽略它并直接调用它们时,服务器没有义务使其工作。这应该更容易通过 Eclipse,只是很多蹩脚的代码。
标签: c++ interface com idispatch