【问题标题】:Building ActiveQt (COM) applications with MinGW使用 MinGW 构建 ActiveQt (COM) 应用程序
【发布时间】:2011-03-09 12:19:51
【问题描述】:

我在 Windows 上使用带有 MinGW 的 Qt 4.6.3 来构建 Qt 应用程序,现在需要向我的应用程序添加一个 COM 接口。我启用了 ActiveQt,但由于缺少 MIDL 编译器的副本而出现链接后错误。我下载了包含 MIDL 的最新 MS Windows SDK 的副本,但现在 MIDL 抱怨它找不到 cl.exe。我能得出的唯一结论是,您只能使用 MS 编译器构建 ActiveQt 应用程序,我宁愿避免这样做。是一种与MinGW一起工作的方法还是我不走运?

【问题讨论】:

    标签: c++ qt com


    【解决方案1】:

    使用 MS 编译器和工具似乎是完成这项工作的唯一可靠方法。

    【讨论】:

      【解决方案2】:

      好吧,您可以使用 MinGW 构建 ActiveQt,但在此之上使用一堆 COM 东西可能是不可能的,因为 MinGW 中可能存在也可能不存在。一些想法:

      1. 将任何 MS SDK 工具与 MinGW 一起使用都不起作用(mingw.org + DXSDK 除外,它在大多数情况下应该可以工作)。

      2. 您确定在编译时链接了所有必要的库吗?如果您不显示确切的错误消息,我将无法提供更多帮助。

      3. mingw-w32/w64 project 试图提供更完整的“Windows SDK for GCC”;它可能包含您正在寻找的库/文件。它们提供了 x64 和 x86 编译器,以及相当不错的 DX 支持。我对他们的 COM 东西没有经验,但我相信它会比 mingw.org 的更完整。您可以随时在论坛或邮件列表中联系开发人员,他们非常有帮助。

      【讨论】:

      • 应用链接正常。问题在于启动 MIDL 的链接后阶段 - MIDL 需要 cl.exe(MS 编译器)。
      【解决方案3】:

      您可以尝试使用 Wine 的 midl、widl 实现。有关在 Windows 上构建的信息,请参阅 Wine wiki page

      如果您想快速运行它,请获取wine-prgs-0.9.14-mingw.zip 并查看它是如何工作的。

      【讨论】:

        【解决方案4】:

        我同意 Rob 的第二篇文章:使用 mingw 构建 ActiveX 对象是一件非常糟糕的事情。 Mingw 有一些关于 ActiveX 的错误:https://bugzilla.mozilla.org/show_bug.cgi?id=203299 和:https://qt.gitorious.org/qt/qt/merge_requests/2710。我杀了一整天来发现它。将 Qt 用于 MSVS,一切都会好起来的。 ;)

        【讨论】:

          【解决方案5】:

          我已经通过下一个方法解决了这个问题:

          安装了 QtCreator、Msys2 和 VS2015 社区。​​p>

          使用批处理脚本启动 Qt Creator:

          @echo off
          call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 8.1
          
          setlocal
          set MSYSTEM=MINGW32
          set MSYS2_PATH_TYPE=inherit
          start "" "C:\msys64\usr\bin\mintty" -i /msys2.ico -e /usr/bin/bash --login -c "/c/Qt/Tools/QtCreator/bin/qtcreator.exe"
          
          exit /b 0
          

          我正在从 Msys2 环境中启动 QtCreator,因为它提供了在我的项目中构建第 3 方所需的标准 Unix 工具。 所以从理论上讲,这并不是必须为您提供 Msys2 的。

          请注意:不要使用 WinSDK 10.0(或更高版本),因为它在 PATH 变量中没有 midl.exe。

          这样做将创建 PATH 环境变量,其中 Qt Creator 优先(因此您将使用 Qt 安装中的 gcc),然后是 Msys2(因此您可以使用标准 Unix 工具),最后是 MSVC 和 WinSDK 8.1(所以当构建你会发现 midl 编译器)。

          现在我成功构建了 dll 并将其传递给了中间形式的 WinSDK,但目前我仍在尝试在系统中注册它。

          【讨论】:

            【解决方案6】:

            我今天确实成功地使用 QT+mingw-w64 创建和调用进程内和进程外服务器,所以这里是一篇文章。

            这是基于 https://doc.qt.io/qt-5/activeqt-server.html 的说明,尽管它们是为 QT 的 Windows 原生构建并使用 MSVC 编写的,因此需要进行一些更改。

            已安装工具

            • MSYS2 已更新至最新版本(截至 2020 年 10 月 29 日)。
            • qtcreatormingw64/mingw-w64(64 位目标),通过 MSYS2 安装。
            • 已安装包 mingw64/mingw-w64-x86_64-qt5-static(这会导致启用 qtcreator 中的“Qt5 Static”套件)。
            • Visual Studio 2019 社区版(这里提供midl.exe)。
            • https://github.com/lucasg/Dependencies - lucasg Dependencies walker。 (不是必需的,但有助于检查您的静态构建是否有效)。

            创建 COM DLL(还没有类型库)

            这些步骤假定您事先熟悉用于“普通”可执行文件的 QtCreator+qmake。

            1. qtactiveqt/examples/activeqt/simple 复制示例项目。我实际上在 QT 的 MSYS2 安装中的任何地方都找不到这个,所以我直接克隆了 QT 源并选择了示例。
            2. 在 QtCreator 的套件管理中,我选择了 qt5-static 64 位套件。这是为了避免由于在运行时找不到 DLL 而导致的任何问题。
            3. 此示例是进程外服务器,因此要更改为进程内服务器,请将以下行添加到 simple.pro 文件中:TEMPLATE=libCONFIG += dll
            4. 在 GCC 中启用静态链接,正如我在此答案中所述:https://stackoverflow.com/a/64583309/1505939
            5. 构建项目。这将给出一个警告,它无法读取simple_res.o,但可以忽略。这应该会成功创建输出文件simpleax.dll,但随后会出现一些与widl 未找到有关的错误消息——我们将在下一节中解决。

            将类型库写入 DLL

            其他 Windows 工具(例如 regsvr32,以及任何其他想要使用 DLL 的客户端)希望能够从 DLL 中读取类型库。

            在前面步骤中创建的 DLL 不包含类型库。我认为这是因为我们的工具链工具都不知道如何创建类型库。相反,我们必须使用 VS 社区提供的midl.exe 来生成类型库。

            在 QtCreator 中有一个应该调用 midl 的构建后脚本。然而,这在 QtCreator 的 MSYS2 风格中不起作用。它似乎只是使用 MSVC 作为工具包为原生风味编写的。

            所以我们必须手动进行后处理,这涉及到:

            • 在MSYS2 shell中,进入simpleax.dll的目录。
            • 运行此命令:idc simpleax.dll -idl simpleax.idl -version 1.0
            • 启动 VS Community 安装附带的“x64 Native Tools Command Prompt”开始菜单项。
            • 导航到simpleax.dll的目录
            • 运行命令:midl simpleax.idl /nologo /tlb simpleax.tlb。 (注意 - 仅将 midl 添加到 MSYS2 路径是行不通的,因为它找不到一堆其他依赖项)。
            • 返回 MSYS2 shell,转至 idc simpleax.dll -tlb simpleax.tlb

            请注意,只有在类型库发生更改时才需要执行所有这些操作(即,您对导出的 COM 对象的类定义进行了更改)。如果只是重建项目,那么只需要最后一步,您可能可以将其作为手动构建步骤添加到 QtCreator 配置中。

            注册并运行测试

            恭喜!您现在应该能够打开提升的命令提示符并运行 regsvr32 simpleax.dll 并使其成功。 (如果不起作用,请运行dependencies -chain simpleax.tlb,然后在最后它会列出所有 DLL 依赖项)。

            注册成功后,我可以使用 VS Community 调用 COM 对象(新建 C++ 控制台项目和 #import "D:\path\to\simpleax.dll",构建,然后创建一个包含 DLL 包装器的 .tlh C++ 头文件)。

            清理类型库

            创建的类型库包含一大堆烦人的 QT 废话。我发现如果你想创建一个不是 ActiveX 控件的 COM 对象,你可以使用QObject 而不是QWidget 作为基类。那么你就不会了解与 GUI 元素有关的大部分内容了。

            此外,从 COM 对象的类定义中取出 Q_CLASSINFO("EventsID",... 行意味着您不会在类型库中获得所有源/接收器的废话(出于某种原因,它决定必须将所有 QT事件沉没在那里)。

            在这样做之后,只剩下大约一屏废话,包括 QPoint 的定义等,我认为这是 QT 的一个错误(因为不需要这些东西)。我发现我可以在调用 midl 之前从 .idl 文件中删除它,嘿,我们有一个可以发布的干净界面。

            进程外服务器

            这也对我有用,与上述步骤相同,但没有第 3 步(即保留为 app 而不是 lib)。通过midl附加类型库的过程是一样的。

            通过testobject.exe -regserver注册类型库不会给你任何消息告诉你它是成功还是失败,所以另一种方法是在提升的MSYS2提示符下使用idc -regserver testobject.exe,然后它会给你一个失败消息。

            我能够通过 VS Community 调用该对象,就像调用进程内服务器一样。

            还有待解决的问题

            • 弄清楚如何在 CMake 中执行此操作。
            • 自动化构建后类型库过程。
            • 让非静态链接正常工作。
            • 自动删除类型库 guff(或报告错误)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-10-17
              • 2012-01-20
              • 2012-10-06
              • 1970-01-01
              • 2021-12-01
              • 1970-01-01
              • 2014-01-17
              • 1970-01-01
              相关资源
              最近更新 更多