博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言调用COM组件
阅读量:6885 次
发布时间:2019-06-27

本文共 2180 字,大约阅读时间需要 7 分钟。

hot3.png

为了更好的理解C的做法,我们要先看一看C++调用COM组件是怎么做的。

一、C++方式

从 Windows 7 开始,任务栏可以显示进度条,就以这个接口为例吧。

ITaskbarList4 *pTaskbar = nullptr;HRESULT hResult = ::CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, __uuidof(ITaskbarList4), reinterpret_cast
(&pTaskbar));

上面的代码中,ITaskbarList4是一个接口(一个只有纯虚函数的类),CoCreateInstance的作用是创建一个ITaskbarList4接口的实例。创建成功后,就可以使用pTaskbar了。

hResult = pTaskbar->HrInit();

二、C方式

在C++代码中,我们用到了接口(类),而C语言是没有类的,那么应该如何做呢?

我们知道,COM组件是二进制兼容的典范。要在C中使用ITaskbarList4接口,我们必须提供一个与ITaskbarList4在内存模型上相同的C变量。

#define STDMETHODCALLTYPE __stdcalltypedef 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(参数表1)= 0;    virtual R_2 Func_2(参数表2) = 0;    // ......    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;};

转载于:https://my.oschina.net/jthmath/blog/483146

你可能感兴趣的文章
Android View 事件分发源码分析
查看>>
vue 2.0 - props
查看>>
RustCon Asia 实录 | Rust 在国内某视频网站的应用
查看>>
Vue遇上Analytics
查看>>
mysql
查看>>
修改max_allowed_packet(允许执行的sql最大长度)
查看>>
node js 处理时间分析
查看>>
判断数据库、表和字段是否存在
查看>>
新手安装postgreSQL后无法连接服务器
查看>>
递归和动态规划
查看>>
java实现简单的控制台管理系统
查看>>
建造模式
查看>>
Java 多线程(四)——线程同步(synchronized、ReentrantLock)
查看>>
遇到Could not load file or assembly ... or one of its dependencies怎么办
查看>>
TCP 上传文件
查看>>
Linux 重定向符:> ,>>, <
查看>>
金融行业注册电子邮箱账号时最需要注意什么?
查看>>
Xhprof安装
查看>>
所谓的linux集群-其实可以so easy
查看>>
关于OOM-killer
查看>>