我目前正在尝试构建一个与 COM 组件交互的 C++ 库(DLL 文件),以使其在 Java 中可用。我的想法是,我将构建一个非常小的 C++ DLL,其中包含一个“包装”COM 组件的类,然后使用 SWIG 将其导出。通过使用 #import 语句,我已经走得很远了:
#import "ComponentName.dll"
然后调用 CoInitialize() 并创建组件的实例(通过 Visual Studio 生成的 IComponentNamePtr 类)。这适用于所有正常的 COM 方法调用,这很好。
但是,我不知道如何让事件正常进行。我看到有一个 IComponentNameEventsPtr 补充了主要的“智能指针”类,但我不知道该怎么做才能让它工作
我已经尝试了以下所有方法来使事件正常运行:
- Pure C++ — 我不知道该怎么做。我尝试创建一个继承自 IComponentNameEvents 类的新类,为所有抽象函数制作 stub ,并重写函数,但函数未标记为虚拟,所以这不起作用。
- MFC — 我无法正确调用 AfxOleInit。谷歌搜索告诉我,从 DLL 调用时调用失败,因为它假定 OLE 已经初始化。我不太确定如何解决这个问题。每次我尝试创建 COM 组件的实例时,我的库都会崩溃(我假设是因为 COM 未正确初始化)
- ATL — 我不知道如何在 ATL 中处理事件。我可以创建类(通过“Simple ATL”向导,然后是“Implement Interface”向导)但不知道如何使用它。我读了Using IDispEventImpl on MSDN但不知道如何使用该 howto 生成的类。我是否也需要通过 ATL 使用 COM 对象(或者我可以使用#import 自动生成的类)?如何“附加”事件监听器类?
- 我读了Event Handling in COM它使用 event_receiver 属性(新的 Visual C++ 统一事件模型的一部分)。最初我不知道如何将它与通过#import 语句创建的 COM 组件的使用相结合。我终于解决了(并且在页面上提到了!)我需要在 #import 语句中使用“embedded_idl”标志,但这破坏了其他东西(我在.tlh 文件)
有人知道怎么做吗?最简单的方法是什么?我的背景是 C# 和 PHP,所以我没有太多在 C++ 中使用 COM 的经验。
tldr:在 C++ DLL 中使用 COM 事件的最简单方法是什么?
最佳答案
在您的代码中实现源接口(interface)(使用任何机制,包括可能使用 midl 编译器生成纯 C 代码)。在您的外部类型库(您正在使用的类型库)中查找如下所示的界面:
[source] interface IOutGoing;
一旦你实现了它,在事件源对象上使用Advise
注册它(使用Unadvise
注销它)
这是一个显示典型用法的片段,假设您采用 MIDL 方式(使用 ATL/MFC,您必须编写更少的代码,但需要了解更多的宏/模板)
class CSink : public IOutGoing
{
public:
// IUnknown
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
// IOutGoing
HRESULT __stdcall GotMessage(int Message);
CSink() : m_cRef(0) { }
~CSink() { }
private:
long m_cRef;
};
IUnknown* pUnknown;
CoCreateInstance(CLSID_XXXXXXXXX, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);
IConnectionPointContainer* pConnectionPointContainer;
hr = pUnknown->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnectionPointContainer);
hr = pConnectionPointContainer->FindConnectionPoint(IID_IOutGoing, &pConnectionPoint);
// Instantiate the sink object.
CSink* mySink = new CSink;
// Give the connectable object a pointer to the sink.
DWORD dwCookie;
pConnectionPoint->Advise((IUnknown*)mySink, &dwCookie);
关于c++ - 在 C++(ATL、MFC 或纯 C++)中为 Java 互操作处理 COM 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5661831/