调用COM组件最简单的语言当然是C++,但在某些情况下,不得不用C语言。本文介绍用C语言调用COM组件的方法。
为了更好的理解C的做法,我们要先看一看C++调用COM组件是怎么做的。
一、C++方式
从 Windows 7 开始,任务栏可以显示进度条,就以这个接口为例吧。
ITaskbarList4 *pTaskbar = nullptr; HRESULT hResult = ::CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, __uuidof(ITaskbarList4), reinterpret_cast<void**>(&pTaskbar));
上面的代码中,ITaskbarList4是一个接口(一个只有纯虚函数的类),CoCreateInstance的作用是创建一个ITaskbarList4接口的实例。创建成功后,就可以使用pTaskbar了。
hResult = pTaskbar->HrInit();
二、C方式
在C++代码中,我们用到了接口(类),而C语言是没有类的,那么应该如何做呢?
我们知道,COM组件是二进制兼容的典范。要在C中使用ITaskbarList4接口,我们必须提供一个与ITaskbarList4在内存模型上相同的C变量。
#define STDMETHODCALLTYPE __stdcall typedef struct ITaskbarList4Vtbl { HRESULT(STDMETHODCALLTYPE *QueryInterface)(ITaskbarList4 *This, const IID *riid, void **ppvObject); ULONG(STDMETHODCALLTYPE *AddRef)(ITaskbarList4 *This); ULONG(STDMETHODCALLTYPE *Release)(ITaskbarList4 *This); HRESULT(STDMETHODCALLTYPE *HrInit)(ITaskbarList4 *This); HRESULT(STDMETHODCALLTYPE *AddTab)(ITaskbarList4 *This, HWND hwnd); HRESULT(STDMETHODCALLTYPE *DeleteTab)(ITaskbarList4 *This, HWND hwnd); // 省略其他代码 } ITaskbarList4Vtbl; typedef struct ITaskbarList4 { ITaskbarList4Vtbl *pVtbl; } ITaskbarList4;上面的C代码中的ITaskbarList4与C++代码中的ITaskbarList4的内存模型是相同的(参看著名的图书《深入探索C++对象模型》),而pVtbl是C++的ITaskbarList4的虚函数表,ITaskbarList4 *This是C++中的this指针。
将类ITaskbarList4的虚函数表全部用C写出来后,就可以使用C调用COM组件了。当然了,这种做法的优雅程度比不上C++方式。
ITaskbarList4* pTaskbar = NULL; HRESULT hr = 0L; hr = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskbarList4, (void**)&pTaskbar); hr = pTaskbar->lpVtbl->HrInit(pTaskbar); hr = pTaskbar->lpVtbl->SetProgressValue(pTaskbar, hWnd, 20ui64, 100ui64);C代码比C++代码多个一个参数,而这个参数传递的正是接口自身。这个参数其实就是C++中的this指针,在C语言中,必须显示地提供它,而在C++中,this指针是隐藏的,所以我们才看到C代码多了一个参数。
三、一般规则
一般而言,如果C++版的COM接口为
class IFunc { public: virtual R_1 Func_1(<span style="font-family: Arial, Helvetica, sans-serif;">参数表1)</span> = 0; virtual R_2 Func_2(<span style="font-family: Arial, Helvetica, sans-serif;">参数表2</span><span style="font-family: Arial, Helvetica, sans-serif;">) = 0;</span> // ...... virtual R_n Func_3(参数表n) = 0; };那么对应的C结构是:
struct Func; typedef struct Func Func; typedef struct FuncVtbl // 虚函数表 { R_1(__stdcall Func_1)(Func *This, 参数表1); R_2(__stdcall Func_2)(Func *This, 参数表2); // ...... R_n(__stdcall Func_n)(Func *This, 参数表n); } FuncVtbl; struct Func { FuncVtbl *pVtbl; };
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/jthmath/article/details/46768069