zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    python测试开发django-1.开始hello world!
    python基础--杂项
    Python基础----函数
    python介绍
    公共Webservice
    divmod(a,b)函数
    模块知识
    第三周作业 修改配置文件
    rsync在windows和linux同步数据的配置过程
    docker学习笔记
  • 原文地址:https://www.cnblogs.com/findumars/p/5277561.html
Copyright © 2011-2022 走看看