我们可以使用 SWIG 为 Qt 应用程序制作 python 绑定吗?

Posted

技术标签:

【中文标题】我们可以使用 SWIG 为 Qt 应用程序制作 python 绑定吗?【英文标题】:Can we use SWIG to make python bindings for Qt application? 【发布时间】:2016-08-01 21:33:01 【问题描述】:

如何使用SWIG绑定到QT应用,我们的情况和这个post的情况差不多,上面写着:

我们有一个大型 C++/Qt 应用程序,其中包含核心的 Swig 绑定。 我们想在 python 中创建新的 UI 工具,需要使用一些 我们的 C++ 小部件。所以我们需要绑定我们的 C++ 小部件。作为我们的核心 绑定是用 Swig 编写的(我们对此很满意)我们需要绑定我们的 具有相同绑定工具的小部件以实现兼容性。

似乎他们已经成功地在 SWIG 中创建了 Qt 的绑定,但使用 swig 包装 QT 似乎并不容易,因为带有宏 Q_OBJECT 的 QT 应用程序将在预编译时生成 moc 文件,并且在编译时使用这些文件。我试过这个:

>> swig -c++ -python application.i
application.h:46: Error: Syntax error in input(3)

它总是给出关于指示 Q_OBJECT 的第 46 行的错误。

我还发现here和here说不可能使用swig来包装QT,我对此感到很困惑,如果它不可行或者如果可以的话,有人可以说明一下吗?关于使用 SWIG 包装 QT 的简单示例。提前致谢。

更新源文件:application.h

#ifndef   APPLICATION_H_
#define   APPLICATION_H_

#include <QApplication>

class frameApplication : public QApplication

    Q_OBJECT

public:
    frameApplication ();
    virtual ~frameApplication();

private slots:
    void OnExitApp();

;
#endif  // APPLICATION_H_

应用程序.i

%module application
%
#include "application.h"
%
%include "application.h"

这是 application.h 的简化版本,使用上面的 SWIG 命令,错误消息除了行号外保持不变。

【问题讨论】:

是的,不仅仅是Q_OBJECT,还有Q_SINGAL/Q_SLOTS等 这就是 swig 无法处理 QT 应用程序的原因,引用上述链接之一:“我不确定是否有完整的 Qt 宏列表,但这里有很多。他们的所有概念我可以通过 C++ 表达吗?这就是他们在内部所做的。他们有一个名为 moc(元对象编译器)的工具,它在任何其他步骤之前在他们的代码上运行。它产生标准 C++,然后编译。问题是它只生成“真正的”cpp 文件,而不是“真正的”头文件,并且如文档中所述,不能依赖 SWIG 来正常处理 C++ 源文件。” 叹息,如果 C++ 编译器本身 可以处理这些文件,那么 SWIG 也可以处理它们。我已经做过很多次了。它工作正常。它们是大声喊叫的有效 C++ 源,一个人必须相信什么样的魔法才能不这样想!在我之后重复:具有 Qt 宏的 .cpp/.h 文件原封不动地传递给 C++ 编译器,并且是有效的 C++。这就是 C++ 框架的全部要点。 moc 所做的唯一想法是生成一些成员定义(不是声明!)和一些静态数据 - Swig 或编译器都不需要这些。 我认为 swig 不需要依赖来生成包装文件。只有当我们将 swig 生成的 wrap 文件编译成 .o 文件时,我们才需要指定依赖关系。如果有人有 QT env,请尝试一下。 正如我所说:当您向 SWIG 提供适当的参数时,它会起作用。 Swig 确实 需要依赖项,因为它需要正确预处理文件!来吧:它对你特别是失败了,因为你没有让它知道Q_OBJECT 是什么。你知道的。 “我认为 swig 不需要依赖来生成 wrap 文件。”考虑到你的问题,你不能这么想。 【参考方案1】:

我们可以使用 SWIG 为 Qt 应用程序制作 python 绑定吗?

是的

发生错误是因为您的头文件使用了 SWIG 不知道的宏。当然,C++ 编译器也不知道它们。

SWIG 需要预处理您的输入。为此,它需要知道 both 到 Qt 的包含路径,以及 Qt 标头工作所需的定义。

在我使用 Widgets 包的特定项目中,在 OSX Qt 安装中,SWIG 需要以下参数,例如:

-DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB \
-I/Qt/5.6.0/lib/QtWidgets.framework/Headers \ 
-I/Qt/5.6.0/lib/QtGui.framework/Headers \ 
-I/Qt/5.6.0/lib/QtCore.framework/Headers \ 
-I/Qt/5.6.0/mkspecs/macx-clang

SWIG 对丢失的包含文件保持沉默有很长的路要走。即使缺少包含文件,它也会尽力解析输入,并对各种标识符做出一些假设,即使它们是未定义的,但是当出现未知宏时,它不能做很多事情。展开为单个标识符。

获得必要的定义 (-D) 和包含路径 (-I) 选项的最简单方法是构建您的代码并从编译器的命令行获取这些选项。 SWIG 有目的地使用与大多数 C/C++ 编译器相同的选项语法 - 以便更轻松地传递该数据。

应该说 SWIG 对信号和槽一无所知:它们只是 C++ 方法。 SWIG 生成的任何绑定都不支持使用 Qt 5 的新 connect 语法来链接信号和插槽。您仍然可以使用 Qt 4 语法,将 C 字符串方法签名传递给 connect,例如:

// with SIGNAL/SLOT macros
connect(obj1, SIGNAL(foo(QString)), obj2, SLOT(bar(QString)));
// without SIGNAL/SLOT macros - as you would call from a SWIG binding
connect(obj1, "2foo(QString)\0", obj2, "1bar(QString)\0");

方法签名需要后缀一个额外的空终止符。信号以'2'为前缀,槽以'1'为前缀,其他可调用方法以'0'为前缀。

除非您使用私有QMetaObjectBuilder,否则您将无法定义新信号或可调用方法;见here。

【讨论】:

以上是关于我们可以使用 SWIG 为 Qt 应用程序制作 python 绑定吗?的主要内容,如果未能解决你的问题,请参考以下文章

SWIG:将其参数从 c++ 修改为 python 的函数

利用Qt制作一个helloworld

使用 Visual Studio 2012 的编译器为 Windows XP 制作 Qt 应用程序

wxlua 绑定不适用于我使用 SWIG 制作的着色器对象

获取 Qt 小部件以更新使用 Qt Designer 制作的 Qt 表单中的鼠标事件

为静态库编译 SWIG Python 包装器?