c++ - 在 C++(ATL、MFC 或纯 C++)中为 Java 互操作处理 COM 事件

标签 c++ visual-studio com

我目前正在尝试构建一个与 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/

相关文章:

c# - C# 中等效的 Char 指针

visual-studio - 有没有办法在 Visual Studio 2015 中调整光标闪烁率?

java - 有没有运行良好的 Java COM 库?

COM - 返回一个对象接口(interface)数组

c++ - "using namespace"用于定义全局函数

C++11 "auto"语义

c++ - 如何在单独文件中定义的成员函数中使用成员变量

c++ - Visual Studio C/C++ 是否支持自动软件预取?

c++ - Visual Studio Force 库导入 C++

c# - 查找 ActiveX 组件的所有属性