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的調用方解決這個問題