调用com对象的坑

1、谏言

最近我在弄64位调用32位dll的问题,在几种IPC之间,最后考虑了调用COM 毕竟我们只在windows平台

2、第一坑–修改编译后都需要重新注册,注册表

一直以为只需要编译就好了,结果调用没反应、报错什么的,需要先撤销注册再进行注册

3、第二坑–多线程调用问题

由于我编写的一个操作 是主线程 创建了 com对象后,有个子线程会一直在后台死循环调用最后回调

我最开始按照传入COM指针去进行调用结果是 没反应 也不报错

反复测试后发现是
主线程调用就有反应
子线程调用就没反应

超级奇怪的问题 最后发现是COM多线程调用会出现问题需要一点操作

IGlobalInterfaceTable* GIT = nullptr;

// 初始化(通常在主线程)
CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, CLSCTX_INPROC_SERVER,
	IID_IGlobalInterfaceTable, (void**)&GIT);

// 注册接口
GIT->RegisterInterfaceInGlobal(read, IID_Name, &Cookie);

首先我们需要一个IGlobalInterfaceTable 的对象,然后注册具体的com对象,我们再在子线程里面进行的查找COM对象
去调用

HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
IICRead* pICRead = nullptr;
/*DWORD cookie = cookie;*/
reinterpret_cast<IGlobalInterfaceTable*>(GIT)->GetInterfaceFromGlobal((DWORD)Cookie, IID_Name, (void**)&pICRead);

这里 pICRead 就是我们查找出来的COM对象 这个对象和主线程是一样的

而我们要传递给子线程的 一个是IGlobalInterfaceTable 、 一个是 DWORD cookie 这个值很重要

是我们 RegisterInterfaceInGlobal 注册COM时的唯一标识符

子线程结束了需要调用COM的Release 与 CoUninitialize函数清除COM环境

当不再需要GIT时 我们一样需要Release 当然 之前我们还需要取消注册 RevokeInterfaceFromGlobal 参数是之前的那个cookie

4、第四坑–COM很多函数都是成对存在的


CoInitializeEx 与 CoUninitialize

RegisterInterfaceInGlobal 与 RevokeInterfaceFromGlobal

CoCreateInstance 与 Release

等等 只要用到COM对象 就需要清理

5、第五坑–COM读取数据块时

比如 现在我需要读取COM对象的函数 其中是返回一个数据块内部的数据的

我之前直接传入指针,发现返回出来的都是错误信息,一查才知道,有专门的手段

BYTE* pData = NULL;// 用于存储读取的数据
SAFEARRAY* p = SafeArrayCreateVector(VT_UI1, 0, 16);
read->Read_IC_Com(&p); // 读取数据到 SafeArray
SafeArrayAccessData(p, (void**)&pData); // 访问 SafeArray 数据
_memccpy(pDataBuff, pData, 0, 16); // 将 SafeArray 数据复制到 pDataBuff
SafeArrayUnaccessData(p);
SafeArrayDestroy(p);

我们需要使用 SafeArray 相关的东西 进行中转才可以

6、第六坑–多个线程同时调用COM对象可能会导致死锁,程序直接卡死

我写了一个这样的情况

我在com对象中写了个函数内部是死循环 条件 是可以通过另一个函数进行修改 从而达到可以结束的条件

问题就在这里了

我在子线程里面去调用这个COM跑死循环的函数

在主线程里面去调用这个可以结束COM死循环的条件函数

然后程序直接卡死

最后我修改死循环来到COM的调用方解决这个问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值