2009-06-03 128 views
12

我需要使用R工具中包含的gcc编译器(R为Windows的统计程序)来编译我的一些代码,问题是我需要使用IDispatch在我创建一个访问COM对象的方法的代码中,并且gcc编译器不支持我正在使用的大部分代码,这基本上就是C++代码。如何在纯C中使用IDispatch来调用COM对象

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

回答

15

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

这是the link to Part 1

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

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

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

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++接口。

+2

请注意,您需要确保您的调用约定匹配,否则您的参数传递顺序和堆栈清理将无法正常工作。确保这些方法被声明为使用'stdcall'调用约定。 – 2009-06-03 20:50:18

+0

这并不能很好地解释C++中的IDispatch使用此调用的事实,因此它通过ecx传递,而不是在堆栈上;而在C中它通过这个通过栈而不是ecx;而CoCreateInstance不关心你是否使用C或C++。不明白为什么其中一个版本不会因错误的调用约定而失败。同样如上所述,您的示例默认为cdecl,而com期望stdcall,因此您最终清理堆栈的次数会有效地破坏堆栈。 – Dmitry 2018-02-12 22:44:19