调用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