c ++使用IDispatch的OLE服务器的MFC SDI DLL调用方法

时间:2014-06-30 17:13:32

标签: c++ dll mfc invoke idispatch

我编写了一个c ++ MFC DLL,它启动了一个非常传统的OLE服务器SDI应用程序。 (我没有选择使用这个OLE服务器,所以我必须让它工作。)

我从C#访问这个c ++ DLL。

我让一切都“有效”。我可以调用DLL的方法,我已经正确地实现了C#委托等等。

我可以直接在C ++中调用OLE服务器的方法并导出它们,以便我的C#应用​​程序调用也调用它们。这是我的“Hello World”,用于从C#中完整地访问OLE服务器功能。

到目前为止一切顺利。

下一步是使这个C ++ DLL尽可能地“传递”,以便C#开发人员可以围绕这个OLE服务器编写业务逻辑。如果从OLE服务器的制造商发生更改或更新,我们不希望更新C ++代码,我们希望响应C#中的更改。

因此即使我可以使用OLEServer.tlb文件中的导入类在C ++中实现方法并将它们传递给C#,我们也不希望最终这样做。我试图通过IDispatch接口调用方法,而我遇到了一些我无法理解的困难。

我将Visual Studio 2010用于非托管C ++和C#。

VARIANT LaserCat::LaserCatCommand(LPCTSTR* p_pMethodNameAndParamsInReverseOrder, UINT p_Count)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  VARIANT result;
  VARIANT* pResult = NULL;
  VariantInit(&result);
  HRESULT hr = NULL;
  DISPID dispid;
  const IID IID_ITriad = {0x60EE772D,0xE076,0x4F58,{0xA8,0xB4,0x2F,0x7A,0x29,0xBB,0x02,0x50}};
  COleException* pError = NULL;
  BOOL HasDispatch = theApp.pTriadView->pTriadItem->Catalog.CreateDispatch(IID_ITriad, pError);
  LPDISPATCH iDisp = theApp.pTriadView->pTriadItem->Catalog.m_lpDispatch;
  LPOLESTR Names[1] = {(LPOLESTR)L"GetInterfaceVersion"};
  hr = iDisp->GetIDsOfNames(IID_NULL, Names, 1, LOCALE_SYSTEM_DEFAULT, &dispid);

  if (hr != S_OK) return result;

  DISPPARAMS* pParams = new DISPPARAMS();
  short maj = 0;
  short min = 0;
  short* nMajor = &maj;
  short* nMinor = &min;
  VARIANTARG Args[2];
  VariantInit(&Args[0]);
  VariantInit(&Args[1]);
  Args[0].piVal = nMinor;
  Args[0].vt = VT_BYREF;
  Args[1].piVal = nMajor;
  Args[1].vt = VT_BYREF;
  pParams->rgvarg = Args;
  pParams->cNamedArgs = 0;
  pParams->cArgs = 2;
  pParams->rgdispidNamedArgs = NULL;
  EXCEPINFO* pExcept = NULL;
  UINT* pArgErrorIndex = NULL;
  LPCTSTR Error = NULL;

  hr = iDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, pParams, pResult, pExcept, pArgErrorIndex);
  if (pExcept != NULL || pArgErrorIndex != NULL || hr != S_OK)
  {
    Error = _T("Error");
    return result;
  }
  result = *pResult;
  return result;
}

上面的以下行给出了“错误的变量类型”错误:

  hr = iDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, pParams, pResult, pExcept, pArgErrorIndex);
顺便说一下,我确信代码可以大大改进,自从我用C ++编写以来已经有好几年了,这只是“开始工作”的第一步,因此没有真正的错误处理等。

我玩过“Args []”类型和值,其中包含“Type Mismatch”错误和“Null Reference Pointers”的变化

.tlb文件导入的函数如下所示:

  short GetInterfaceVersion(short * nMajor, short * nMinor)
  {
    short result;
    static BYTE parms[] = VTS_PI2 VTS_PI2 ;
    InvokeHelper(0x178, DISPATCH_METHOD, VT_I2, (void*)&result, parms, nMajor, nMinor);
    return result;
  }

哦,尽管我将“pMethodNameAndParamsInReverseOrder”作为参数传递,但我只是对它进行硬编码以使这个简单的方法正常工作。一旦我使用了这个和其他一些方法,我就打算通过IDispatch来处理COM接口实现的任何方法。

任何帮助都会受到赞赏,主要是为了让这个工作,但我也很感激有关改进代码的任何指示,我有用C ++学习的东西

感谢您!

BTW,如果这有助于澄清事情,那么App.pTriadView-> pTriadItem->目录就是我正在实施的COM类

编辑:

感谢@HansPassant(见第一条评论)我看到了我所缺少的东西。不幸的是,我已经找到了修复它的下游结果。 VARIANT“pResult”空无一人。我现在将继续追捕,但任何想法都会受到欢迎:)

0 个答案:

没有答案