【问题标题】:How to use IDispatch in plain C to call a COM object如何在纯 C 中使用 IDispatch 来调用 COM 对象
【发布时间】:2010-10-31 01:46:29
【问题描述】:

我需要使用 R 工具中包含的 gcc 编译器(R 用于 windows 的统计程序)编译我的一些代码,问题是我需要在我的代码中使用 IDispatch 来创建一个访问 COM 的方法对象,而 gcc 编译器不支持我用来执行此操作的大部分代码,这些代码基本上是 C++ 代码。

所以我的问题是如何在 C 中使用 IDispatch 来创建 COM 对象,而不必依赖于 MFC、.NET、C#、WTL 或 ATL。我相信如果我这样做,我将能够毫无问题地编译我的代码。

【问题讨论】:

    标签: c com gcc activex idispatch


    【解决方案1】:

    您也可以使用disphelper 库。

    【讨论】:

      【解决方案2】:

      CodeProject 上有一篇很棒的文章,题为“COM in plain C”。

      这里是the link to Part 1

      在那篇文章和作者的后续跟进中有很多关于在 C 中使用 COM 的非常好的信息(我认为该系列中有 3 或 4 个)。

      编辑:
      我错了,有 8 个部分!

      Part 2
      Part 3
      Part 4
      Part 5
      Part 6
      Part 7
      Part 8

      【讨论】:

      • 这确实是一个非常好的教程,我正在看它,第一部分解释了如何创建一个我已经拥有的 COM 对象,问题是我的 COM 对象是用 C# 编写的,我在教程中看到您需要创建一个包含(.h)文件,您必须在其中指定 COM 对象中的 VTable、GUID 和结构,现在,即使我的 COM 对象是 C#,我可以这样做吗?跨度>
      • 嗯 - 我想这是可能的,你是否在注册表中注册了你的 C# COM 对象?我认为这就是所有必要的。 COM是二进制标准,所以不管是C#、C++、VB等实现的VTable都应该是一样的。
      【解决方案3】:

      通常,C++ IDispatch 接口只是一个函数指针表。 在 C 中,它看起来像:

      typedef struct {
        HRESULT(*pQueryInterface)(void* this, REFIID riid, void **ppvObject);
        ULONG(*pAddRef)(void* this);
        ULONG(*pRelease)(void* this);
        HRESULT(*pGetTypeInfoCount)(void* this, unsigned int* pctInfo);
        HRESULT(*pGetTypeInfo)(void* this, unsigned int iTInfo,LCID lcid, ITypeInfo** ppTInfo);
        HRESULT(*pGetIDsOfNames)(void* this, REFIID riid, OLECHAR** rgszNames, unsigned int cNames, LCID lcid, DISPID* rgDispId);
       HRESULT(*pInvoke)(void* this, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, unsigned int* puArgErr);
      } IDispatch_in_C;
      

      请注意,每个方法都有一个 THIS 指针作为第一个参数,并且您需要定义更多类型,例如 ITypeInfo、REFIID、DISPID 等。

      所以,这是一项艰巨的任务。但是可以用纯 C 创建 C++ 接口。

      【讨论】:

      • 请注意,您需要确保您的调用约定匹配,否则您的参数传递顺序和堆栈清理将无法正常工作。确保将这些方法声明为使用“stdcall”调用约定。
      • 这并不能完全解释 C++ 中的 IDispatch 使用 thiscall 的事实,因此它通过 ecx 而不是在堆栈上传递 this;而在 C 中,它通过堆栈而不是 ecx 传递它;而 CoCreateInstance 不在乎您使用的是 C 还是 C++。为什么其中一个版本不会由于错误的调用约定而失败是没有意义的。同样如上所述,您的示例默认为 cdecl 而 com 需要 stdcall,因此您最终清理堆栈两次有效地破坏了它。
      猜你喜欢
      • 2011-01-07
      • 2011-12-25
      • 1970-01-01
      • 2010-11-24
      • 2011-05-16
      • 2014-03-05
      • 2013-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多