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

时间:2016-08-01 21:33:02

标签: python c++ qt swig

如何使用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)

它总是给出第46行的错误,表示Q_OBJECT。

我还发现herehere说使用swig包裹QT是不可能的,我对此非常困惑,如果不是这样,有人会对此有所了解吗?可行或如果可以的话,给出一个关于使用SWIG wrap 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_

application.i

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

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

1 个答案:

答案 0 :(得分:3)

  

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

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

SWIG需要预处理您的输入。要做到这一点,它需要知道两个 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对于遗漏包含文件保持沉默还有很长的路要走。即使在包含文件丢失的情况下,它也会尽力解析输入,并对各种标识符的内容做出一些假设,即使它们是未定义的,但是如果出现了未知的宏,那么它就不会做多少&# 39; t只是扩展为单个标识符。

获得必要的定义(-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");

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

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