这个问题捣鼓了两天,现在终于解决了,做个笔记分享给大家,以免走弯路

起初,我的想法是在DLL中写一个interface并从函数中导出这个interface,像这样的代码

  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”

创建成功后接口是这样的

  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}

最后实现

  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不用注册就能用,当然注册的话调用起来会更方便

  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. }

最后,调用部分

  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

Qt调用Delphi编写的COM组件的更多相关文章

  1. 分享一次C#调用Delphi编写Dll程序

    1.前言: 最近接手了一个项目需要和Delphi语言编写的一个系统进行一些接口的对接,数据在传输过程中采用Des加密方式,因为Delphi 平台的加密方式和C#平台的加密方式不互通,所以采用的方式是C ...

  2. nodejs调用delphi编写的dll

    公司的业务需要,nodejs要读取文件版本号. 同事要求我用delphi编写dll,以供nodejs调用,结果通过json返回. delphi代码如下: function GetFileInfo(AP ...

  3. QT 调用VS2015编写的Dll

    最近在用QT调用VC生成的库,QT使用的是MinGW调试器,出现与动态库不兼容的问题,最后发现QT只能识别VC生成的C格式下的动态库 也就是在导入导出设置时加入extern "C" ...

  4. C# 调用delphi编写的dll

    技术实现 如何逐步实现动态库的加载,类型的匹配,动态链接库函数导出的定义,参考下面宏定义即可: #define LIBEXPORT_API extern "C" __declspe ...

  5. JS调用Delphi编写的OCX控件

    原文:http://www.mamicode.com/info-detail-471283.html 一.使用Delphi XE2编写OCX控件 生成OCX工程: 1.File-New-Other,在 ...

  6. JavaScript学习笔记之JavaScript调用C#编写的COM组件

    1.新建一个C#类库项目:MyCom: 2.修改 Properties 目录下的 AssemblyInfo.cs(程序集文件) 中的 ComVisible 属性为 true: 3.项目->属性- ...

  7. [JNA系列]Java调用Delphi编写的Dll之实例Delphi使用PWideChar

    Delphi代码 unit UnitDll; interface uses StrUtils, SysUtils, Dialogs; function DoBusinessWide(pvData: P ...

  8. [JNA系列]Java调用Delphi编写的Dll之实例Delphi使用PAnsiChar

    Delphi代码 unit UnitDll; interface uses StrUtils, SysUtils, Dialogs; function DoBusinessAnsi(pvData: P ...

  9. [JNA系列]Java调用Delphi编写的Dll之JNA使用

    介绍 给大家介绍一个最新的访问本机代码的 Java 框架 —JNA . JNA(Java Native Access) 框架是一个开源的 Java 框架,是 SUN 公司主导开发的,建立在经典的 JN ...

随机推荐

  1. cocos2dx进阶学习之CCEGLView

    继承关系 CCEGLView-> CCEGLViewProtocol CCEGLView是窗口,在不同平台上有不同的实现,而CCEGLViewProtocol是CCEGLView定义的接口,所以 ...

  2. Linux c c++ 开发调试技巧

    看到一篇介绍 linux c/c++ 开发调试技巧的文章,感觉挺使用,哪来和大家分享. 通向 UNIX 天堂的 10 个阶梯Author: Arpan Sen, 高级技术人员, Systems Doc ...

  3. 对base-adapter-helper的简单分析

    在微博上看到了这篇Android ListView适配器应该这样写,受益匪浅. 于是依据文章结尾的介绍来到了base-adapter-helper的github,地址:https://github.c ...

  4. UVA 10340 (13.08.25)

    Problem E All in All Input: standard input Output: standard output Time Limit: 2 seconds Memory Limi ...

  5. 【Flume NG用户指南】(1)设置

    作者:周邦涛(Timen) Email:zhoubangtao@gmail.com 转载请注明出处:  http://blog.csdn.net/zhoubangtao/article/details ...

  6. 蓝牙Profile的概念和常见种类

    蓝牙Profile Bluetooth的一个很重要特性,就是所有的Bluetooth产品都无须实现全部 的Bluetooth规范.为了更容易的保持Bluetooth设备之间的兼容,Bluetooth规 ...

  7. arm: 使用结构体操作寄存器

    使用结构体操作寄存器: //寄存器赋值和取值的时候,要注意寄存器的长度,有的寄存器的值只有8位. //还要注意,使用volatile修饰寄存器变量.volatile 参考http://www.cnbl ...

  8. js中with、this的用法

    with 语句 为一个或一组语句指定默认对象. 用法:with (<对象>) <语句>; with 语句通常用来缩短特定情形下必须写的代码量.在下面的例子中,请注意 Math ...

  9. windows下apache如何完整卸载?

    1.运行services.msc,在服务中停止 apache 服务.2.运行命令行程序,输入 sc delete apache,删除该服务3.删除apache文件夹.

  10. Linux 经典电子书共享下载

    Linux 经典电子书共享下载 Linux网络管理员指南--Linux领域两位领导人物的作品—相当于“Linux 文档项目”.rar vim用户手册_603.0.pdf [Linux系统管理技术手册( ...