2009-06-03 52 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