Qt調用Delphi編寫的COM組件


 這個問題搗鼓了兩天,現在終於解決了,做個筆記分享給大家,以免走彎路

起初,我的想法是在DLL中寫一個interface並從函數中導出這個interface,像這樣的代碼

[delphi]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. ICom1 = interface  
  2.   function Show(V1, V2: Integer): Integer stdcall;  
  3. end;  

最后均以失敗告終,后來想到各種編譯器對編譯后的二進制組織方式是不同的
比如上面的代碼如果用Delphi編寫的Exe去調用就是沒問題的,而用其他語言則可能會有問題
網上有很多跨語言調用方案是用虛類來解決,也許有些時候是可以正常調用,但是這種做法並不規范,容易出問題

這里就需要通過一個標准,一個與語言無關的標准,也就是微軟的COM組件了
所以得改下這個DLL

新建一個Automation Object 

 

 

注意,這里一定要用Automation Object,而不要用COM Object,因為后者不支持自動化調用
而QAxObject只支持自動化對象,如果你嘗試去調用一個不支持自動化的COM Object會得到一條消息

“QAxBase::dynamicCallHelper: Object does not support automation”

 

創建成功后接口是這樣的 

[delphi]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. ICOM2 = interface(IDispatch)  
  2.   ['{53952FF2-94A4-4B14-9C38-E4E56C87940A}']  
  3.   function Show(v1: Integer; v2: Integer): Integer; stdcall;  
  4. end;  

注意,我們在Exe中查詢需要用到的GUID是類ID而不是這里的接口ID,在Delphi自動生成的 XXX_TLB.pas 文件中是有這個GUID的
我這里的是 {0EA6D9F4-0587-4AB9-91AD-9CD657B0787D}

最后實現 

[delphi]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. function TCOM2.Show(v1, v2: Integer): Integer;  
  2. begin  
  3.   OutputDebugString(PChar(Format('TCom2(%d, %d)', [v1, v2])));  
  4.   Result := 2;  
  5. end;  

現在到Qt中,首先寫一個函數,功能是從一個COM DLL中動態創建接口實例
這樣用的好處是COM DLL不用注冊就能用,當然注冊的話調用起來會更方便 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. LPUNKNOWN CreateComObjectFromDll(const QString &dll, REFCLSID clsid)  
  2. {  
  3.     QLibrary lib(dll);  
  4.     if (lib.load()) {  
  5.         typedef HRESULT (__stdcall *DllGetClassObject)(REFCLSID, REFIID, LPVOID*);  
  6.         DllGetClassObject getClassObject = (DllGetClassObject)lib.resolve("DllGetClassObject");  
  7.         if (getClassObject != nullptr) {  
  8.             IClassFactory *factory;  
  9.             if (getClassObject(clsid, IID_IClassFactory, (LPVOID*)&factory) == S_OK) {  
  10.                 LPUNKNOWN ret = nullptr;  
  11.                 factory->CreateInstance(nullptr, IID_IUnknown, (void**)&ret);  
  12.                 return ret;  
  13.             }  
  14.         }  
  15.     }  
  16.     return nullptr;  
  17. }  

最后,調用部分 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. LPUNKNOWN obj = CreateComObjectFromDll("com", cid);  
  2. QAxObject o(obj);  
  3. o.dynamicCall("Show(int, int)", 123, 456);  

參數cid就是接口類GUID


 

可以看到輸出窗口正常顯示了結果。

 

總結:起初沒有使用標准的COM接口,走了不少彎路。。。 -_-!

http://blog.csdn.net/aqtata/article/details/9163689


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM