用SWIG来生成Qt C++动态库的Python绑定

来源:互联网 发布:万文数据库 编辑:程序博客网 时间:2024/06/13 14:45

以前写过一个博客介绍用SIP来做C++的Python绑定。这几天看了看SWIG,挺不错的工具,支持把C/C++绑定成多种语言(Perl, PHP, Python, Tcl, Ruby, PHP, C#, Java等等)。最重要的是SWIG文档非常全,想想Shiboken,哎。。。

我的环境如下

  • Windows XP
  • Python 2.7.2
  • Qt SDK 4.8.4
  • MinGW (gcc 4.4.0)
  • SWIG 2.0.9

下载SWIG

  • 下载网址 https://sourceforge.net/projects/swig/files/swigwin/
  • 直接下载它的zip包: swigwin-2.0.9.zip, 解压之后就可以用了

目标

  1. 使现有的Qt C++动态链接库能被Python调用。而且
  2. 不能重新编译该动态链接库
目前我们有该库的头文件(bar.h),库文件(libbar.a, bar.dll)

问题和方法

既然我们不能修改bar.dll库的代码,那么我们只能写一个C++ Wrapper 类来包装bar.dll,SWIG可以把这个Wrapper类绑定成Python库。

生成动态链接库bar.dll

首先我们来生成下面要用到的动态库bar.dll. 我们会用到文件bar.h, bar.cpp, bar.pro
  • bar.h
#ifndef BAR_H#define BAR_H#if defined(BAR_LIBRARY)      #define BARSHARED_EXPORT __declspec(dllexport)  #else      #define BARSHARED_EXPORT __declspec(dllimport)  #endif#include <string>using namespace std;class QString;class BARSHARED_EXPORT Bar {public:    Bar();    ~Bar();    int len(const QString &str);};#endif // BAR_H
  • bar.cpp
#include <QString>#include "bar.h"Bar::Bar(){}Bar::~Bar(){}int Bar::len(const QString &str){    return str.size();}
  • bar.pro
TEMPLATE = libQT       -= guiDEFINES += BAR_LIBRARYHEADERS += bar.hSOURCES += bar.cpp

现在建一个bar目录,把上面三个文件拷到目录里,编译成动态库(libbar.a, bar.dll)。
D:\GitHub\exercise\swig>cd barD:\GitHub\exercise\swig\bar>qmakeD:\GitHub\exercise\swig\bar>make release
生成的库文件应该在bar\release目录下了。
D:\GITHUB\EXERCISE\SWIG\BAR│  bar.cpp│  bar.h│  bar.pro│  bar.pro.user│  Makefile│  Makefile.Debug│  Makefile.Release│  test.cpp│├─debug└─release        bar.dll        bar.o        libbar.a        test.o

用SWIG生成Python绑定

现在我们写一个Wrapper类BarBinding来调用Bar.
//barbinding.h#ifndef BARBINDING_H#define BARBINDING_H#include<string>using namespace std;class Bar;class BarBinding{public:    BarBinding();    ~BarBinding();    int len(const string &str);private:    Bar *p;};#endif // BARBINDING_H
这里注意barbinding.h头文件里没有用任何Qt相关的类。SWIG目前没有提供对Qt类的直接支持,所以,我们用C++标准类string来代替QString.
//barbinding.cpp#include <QString>#include "barbinding.h"#include "bar.h"BarBinding::BarBinding(){    p = new Bar();}BarBinding::~BarBinding(){    if (p) {        delete p;        p = NULL;    }}int BarBinding::len(const string &str){    if (p) {        QString s(str.c_str());        return p->len(s);    } else {        return -1;    }}
接着写一个SWIG的接口文件bar.i来描述我们需要绑定到Python的那些类和方法。基本上bar.i就是对barbinding.h头文件的一个详细描述。
/* File : bar.i */%module bar%include "std_string.i"using namespace std;%{#include "barbinding.h"%}/* Let's just grab the original header file here */%include "barbinding.h"
运行SWIG来生成绑定用的C++和python文件
D:\GitHub\exercise\swig\bar>D:\swigwin-2.0.9\swig.exe -python -c++ bar.i
现在bar目录下多了如下两个文件

接着运行如下的.pro文件生成最后的绑定
TEMPLATE = libQT       -= guiTARGET = _barINCLUDEPATH += $$PWD \    D:/Python27/includeHEADERS += barbinding.hSOURCES += barbinding.cpp \bar_wrap.cxxLIBS += -L$$PWD/release -lbar -LD:/Python27/libs -lpython27

D:\GitHub\exercise\swig\bar>qmake barbinding.proD:\GitHub\exercise\swig\bar>make  release
现在bar\release目录下就生成了我们需要的python绑定"_bar.dll". 

我们需要把“_bar.dll"改名成Python能认识的后缀名"_bar.pyd".此外还要把bar\bar.py拷贝到bar\release\bar.py。
D:\GitHub\exercise\swig\bar>copy bar.py release\bar.py        1 file(s) copied.D:\GitHub\exercise\swig\bar>rename release\_bar.dll _bar.pyd
到此我们就完成了对bar.dll库的绑定。release目录下的三个文件(调用关系:bar.py->_bar.pyd->bar.dll)就是用python来调用bar.dll需要的全部东西了。

来试试我们生成的Python绑定









原创粉丝点击