码迷,mamicode.com
首页 > 编程语言 > 详细

C语言调用COM组件

时间:2015-07-06 10:24:29      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:c语言   c++   com组件   调用   纯c   

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

C语言调用COM组件

标签:c语言   c++   com组件   调用   纯c   

原文地址:http://blog.csdn.net/jthmath/article/details/46768069

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!