处理用于Java互操作的C++(ATL,MFC或纯C++)中的COM事件

Dan*_*gro 8 c++ com visual-studio

我目前正在尝试构建一个与COM组件接口的C++库(DLL文件),以使其在Java中可用.我的想法是,我构建了一个非常小的C++ DLL,其中包含一个"包裹"COM组件的类,然后使用SWIG导出它.我使用#import语句得到了很多:

#import "ComponentName.dll"
Run Code Online (Sandbox Code Playgroud)

并调用CoInitialize()并创建组件的实例(通过Visual Studio生成的IComponentNamePtr类).这适用于所有正常的COM方法调用,这很好.

但是,我无法弄清楚如何使事件发挥作用.我看到有一个IComponentNameEventsPtr补充了主要的"智能指针"类,但我无法弄清楚要做些什么才能让它工作

我已经尝试了以下所有方法来使事件发挥作用:

  • 纯C++ - 我无法弄清楚如何做到这一点.我尝试创建一个继承自IComponentNameEvents类的新类,为所有抽象函数创建存根,并覆盖函数,但函数未标记为虚函数,因此不起作用.
  • MFC - 我无法正确调用AfxOleInit.谷歌搜索告诉我,从DLL调用时调用失败,因为它假定OLE已经初始化.我不太确定如何解决这个问题.每次我尝试创建COM组件的实例时,我的库都崩溃了(我假设因为COM没有正确初始化)
  • ATL - 我无法弄清楚如何在ATL中完成这些事件.我可以创建类(通过"简单ATL"向导,然后"实现接口"向导),但无法解决如何使用它.我在MSDN上阅读使用IDispEventImpl,无法解决如何使用该howto生成的类.我是否也需要通过ATL使用COM对象(或者我可以使用#import自动生成的类)?如何"附加"事件监听器类?
  • 在COM中读取事件处理,它使用event_receiver属性(新的Visual C++统一事件模型的一部分).最初我无法弄清楚如何将它与通过#import语句创建的COM组件的使用相结合.我终于解决了(在页面上提到了!)我需要在#import语句中使用"embedded_idl"标志,但这打破了其他事情(我有一堆"期待类型规范接近"错误.tlh文件)

有谁知道如何做到这一点?什么是最简单的方法?我的背景是C#和PHP,所以我在C++中使用COM的经验不多.

tldr:在C++ DLL中使用COM事件最简单的方法是什么?

Dan*_*gro 2

实际上,我自己使用统一事件模型实现了这一点。我在让它发挥作用方面的经验中的一些注意事项:

然后添加一个

typedef struct StructName StructName;
Run Code Online (Sandbox Code Playgroud)

对于每个抛出错误的结构

  • 完成后,您应该能够初始化 COM 并创建对象的实例。丑陋的示例代码:

    IComponentName blah;
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        MessageBox(NULL, "Failed to initialize COM", "Hi!", 0);
        throw "Failed to initialize COM";
    }
    
    try
    {
        hr = blah.CreateInstance("Something.Something");
        if (FAILED(hr))
        {
            CoUninitialize();
            MessageBox(NULL, "Failed to initialize the COM library!!", "Hi!", 0);
            throw "Failed to initialize the COM library";
        }
    }
    catch (...)
    {
        MessageBox(NULL, "Exception occured when initialising library!", "Error", 0);
        CoUninitialize();
        throw "Exception occured when initialising library!";
    }
    
    Run Code Online (Sandbox Code Playgroud)

获得 COM 对象后,您可以按照 MSDN“COM 中的事件处理”一文连接事件:

__hook(&IComponentNameEvents::OnWhatever, blah, &EventHandlerClass::OnWhatever);
Run Code Online (Sandbox Code Playgroud)

请务必在调用 CoUninitialize() 之前取消挂钩所有事件,否则会出现错误。