为 MFC 自动化实现 IDispatch 接口

问题描述

我有一个不支持 MFC 的 COM 项目,需要通过 MFC 接口与另一个 App 通信。 我不能直接在 MFC 接口中使用我的 COM 项目,因为它不是 MFC 项目。

一个解决方案是为 MFC 接口创建一个自动化接口,我可以将其用作一个层,我的 COM 项目可以通过该层与 MFC 项目进行通信。

据我所知,自动化应用程序将在不同的线程中运行。我的 COM 项目将从自动化接口调用方法调用 MFC 接口。

自动化项目及其 IDL 文件已提供给我,并为我提供了一个 Pure dispinterface。

在将 Idispatch 接口的实现集成到我的 COM 项目之前,我决定创建一个新的 C++ 控制台项目,以便专注于简单地使用自动化接口。 使用 microsoft (https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/implementing-the-idispatch-interface) 提供的文档,我实现了 Idispatch 接口,如下所示:

#include "TTAutomate.h"

HRESULT hresult;
disPID dispid;
disPParaMS dispparamsNoArgs = { NULL,NULL,0 };
EXCEPINFO excepinfo;
UINT nArgErr;
ClassFromIDL* m_ClassFromIDL;
_DTTAutomateEvents* m_DTTAutomateEvents;
_DTTAutomate* m_DTTAutomate;


hresult = OleInitialize(NULL);

// OLE function CoCreateInstance starts application using GUID.
hresult = CoCreateInstance(CLSID_TTfromIDL,CLSCTX_INPROC_SERVER,DIID__DTTAutomateEvents,(LPVOID*)m_Automate);


// Call QueryInterface to see if object supports Idispatch.
hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL,(LPVOID*)pdisp);

// Retrieve the dispatch identifier for the SayHello method.
// Use defaults where possible.
OLECHAR* szMember = "SayHello";
disPID dispid_Item;
hresult = pdisp->GetIDsOfNames(
    IID_NULL,&szFunction,1,LOCALE_USER_DEFAULT,&dispid_Item);

首先,实现与文档中的实现有点不同,因为有一行:

hresult = CoCreateInstance(CLSID_Hello,CLSCTX_SERVER,IID_IUnkNown,(void **)&punk);

我会收到错误“放大器未定义”。

使用上面的代码,我目前收到一个错误,指出 const char * 无法初始化 OLECHAR *

在我的 COM 项目中,我有一行:

LPOLESTR szFunction = OLESTR("SayHello");

编译但我的测试项目中的同一行不起作用。

我是否错过了一些要添加的包含? 我没有创建正确类型的测试项目吗?

解决方法

于是,我找到了一种方法来解决我的代码,以便它编译但不能完全确定,如果它是一个妥善的解决办法:

#include "TTAutomate.h"
#include <string>

HRESULT hresult;
DISPID dispid;
DISPPARAMS dispparamsNoArgs = { NULL,NULL,0 };
EXCEPINFO excepinfo;
UINT nArgErr;
ClassFromIDL* m_ClassFromIDL;
IDispatch* m_Automate; // fixed


hresult = OleInitialize(NULL);

// OLE function CoCreateInstance starts application using GUID.
hresult = CoCreateInstance(CLSID_TTfromIDL,CLSCTX_INPROC_SERVER,DIID__DTTAutomateEvents,(void**)&m_Automate); // fixed


// Call QueryInterface to see if object supports IDispatch.
hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL,(void**)&pdisp); // fixed

// Retrieve the dispatch identifier for the SayHello method.
// Use defaults where possible.

// here I create a wchar_t* variable as LPOESTR is casted from that.
std::string functionName = "SayHello";
int wchars_num = MultiByteToWideChar(CP_UTF8,functionName.c_str(),-1,0);
wchar_t* wstr = new wchar_t[wchars_num];

LPOLESTR szMember = wstr;
DISPID dispid_Item;
hresult = pdisp->GetIDsOfNames(
IID_NULL,&szFunction,1,LOCALE_USER_DEFAULT,&dispid_Item);

我现在得到一个E_NOINTERFACE不支持此接口,但它可能是无关的这个话题。