使用Swig封装C++到Python的心得--01
来源:互联网 发布:tomcat8w java options 编辑:程序博客网 时间:2024/05/16 08:15
一.简述
前一段时间由于工作需要重点学习了一下用Swig来封装C++代码到Python的知识,期间遇到一些问题,也有一些心得体会,特此记录。
本文只涉及封装C++到Python,其他诸如封装到Java等没有涉及。
假设读者对Python和C++这两种语言都有一定的了解,到底要什么程度,我也说不清。
本文的所有知识均来自于Swig的帮助文档《SWIGDocumentation.pdf》和我的实践,不一定完全正确。
二.环境搭建
我不想忽略细节,所以我尽量详细,。
我下载swigwin-1.3.33.zip,在H:/3rdTools目录下直接解压缩,即把swig安装到H:/3rdTools/swigwin-1.3.33目录中,将H:/3rdTools/swigwin-1.3.33加入VC的可执行文件路径。
我使用的是Visual Studio 2005,
我下载python-2.4.4.msi,安装到H:/3rdTools/Python24目录,并在PATH环境变量中加入H:/3rdTools/Python24,将H:/3rdTools/Python24/include加入VC的Include路径,将H:/3rdTools/Python24/libs加入VC的Library路径。
让我们从一个Helloworld的例子入手,在Windows上制作一个DLL库,并将其封装成Python的一个Module,然后在Python中import这个Module,调用其中提供的函数,从而显示出“HelloWorld!”。 新建一个Win32 Console Application,注意在Application Settings中选择DLL以及空项目。完成后将工程的配置改成release(主要是因为我用的Python库是Release版的,而非Debug版的)。 具体工程参见practise_swig/HelloWorld,首先向工程里添加HelloWorld.hpp和HelloWorld.cpp文件,里面的内容就是基本的HelloWorld函数。 接下来的工作就是要把这个函数进行封装,使得我们能够在Python中使用该函数。用C++来扩展Python时常用的方式是制作一个动态库,在其中按照Python的规定(详见Python的帮助)来定义一些函数(其形式往往是这样的PyObject * wrap_HelloWorld (PyObject *self, PyObject *args)),这种函数的内容主要是把从Python来的输入参数(由PyObject *args所指),变换成普通的C++类型,然后调用需要封装的C++函数(上文在HelloWorld.cpp中定义的HelloWorld函数就是一个简单的例子)对这些输入进行处理,再把得到的返回值转换成对应的Python的数据类型,最后返回到Python中去。在一定程度上,只要内部具体负责数据处理的函数的输入输出形式确定之后,外层的封装函数的形式也就确定了(当然,封装形式可能不只一种)。当然撰写外层封装函数的工作可以由人来完成,但最好的方法是由机器来生成,Swig就是这样一种机器了。只要告知其我们要封装什么,它就可以帮我们生成封装函数的代码。只要把这些代码和我们自己的代码放在一起,编译成一个动态库,然后就可以在Python中使用我们自己的函数了。 从而所有关于如何使用Swig的重点都转移到如何告知Swig我们要封装什么,以及如何使用Swig封装出的接口上来了。 我们通过一个文本文件(该文件通常以.i为扩展名)来告知Swig我们需要其封装什么东西。下面是HelloWorld工程里的HelloWorld.i文件。 %module HelloWorld %header %{ #include "HelloWorld.hpp" %} int HelloWorld(int iDate); 通过如下命令行,控制Swig对该文件进行处理。 swig -c++ -python -o HelloWorld_wrapper.cpp HelloWorld.i 处理的结果是生成两个新的文件,一个是HelloWorld.py,一个是HelloWorld_wrapper.cpp。在Python中使用import HelloWorld,就会去加载HelloWorld.py文件,而HelloWorld.py文件的第一句就是import _HelloWorld。_HelloWorld是什么,它是一个需要我们来制作的动态库,即我们要把Swig生成的HelloWorld_wrapper.cpp和我们自己写的HelloWorld.hpp、HelloWorld.cpp文件放在一起制作出一个名为_HelloWorld.dll的动态库来。 Swig生成的文件的名字和内容由HelloWorld.i文件的内容以及swig执行的命令行参数的共同决定。先来说说命令行参数 “-c++”表示要封装C++代码(不写默认是封装C代码),“-python”表示要封装成Python接口(Swig还可以封装成Java、Ruby等接口),“HelloWorld_wrapper.cpp”表示指定要生成的C++代码文件的名字。 HelloWorld.i文件分为3个部分,首先是 %module HelloWorld 表示要生成的Module的名字是HelloWorld(即要生成HelloWorld.py文件)。 然后是 %header %{ #include "HelloWorld.hpp" %} 凡是出现在%header%{……%}对中的内容都会原封不动的出现在HelloWorld_wrapper.cpp文件的头部位置。 最后是 int HelloWorld(int iDate); 指明我们要封装的C++函数。 这里我们再详细描述一下使用VC2005制作_HelloWorld的过程: 1. 新建一个Win32 Console Application,要是空的DLL工程,工程配置使用release; 2. 添加HelloWorld.hpp、HelloWorld.cpp两个文件到工程; 3. 在工程中新建HelloWorld.i文件,内容见上文; 4. 修改HelloWorld.i的属性,使用自定义编译工具(Custom Build Tool),命令行(Command Line)内容为swig -c++ -python -o $(InputName)_wrapper.cpp "$(InputPath)",输出(Outputs)为$(InputName)_wrapper.cpp; 5. 编译HelloWorld.i文件,将新生成的HelloWorld_wrapper.cpp文件加入工程; 6. 修改工程的配置属性(Configuration Properties),包括 LinkeràGeneralàOutput File改成$(OutDir)/_HelloWorld.dll Build EventsàPost-Build EventàCommand Line改成 echo "copy $(InputDir)/HelloWorld.py $(TargetDir)" copy "$(InputDir)/HelloWorld.py" "$(TargetDir)" 还有一些配置在VC2005里是默认的,但在VC2003里不是的,请引起注意,包括 1. C/C++àCode GenerationàRuntime Library要选择Multi-threaded DLL (/MD) 2. C/C++àLanguageàTreat wchar_t as Built-in Type要选择yes(如果转换不涉及wchar等,则无需处理这一项) 3. C/C++àLanguageàEnable Run-Time Type Info要选择yes(这个和Swig无关,但有时有些编译问题就是由于这个选项造成的,譬如使用TAO中的any,当然这是题外话了,读者可以忽略) 一旦_HelloWorld.dll制作完成后,就可以在Python中使用了。大致用法如下(_HelloWorld.dll和HelloWorld.py文件都已在practise_swig/release目录中): 在cmd窗口,进入practise_swig/release目录,运行Python,进入交互式界面: H:/WORKSPACE/renStudy/swig/practise_swig/release>python Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import HelloWorld >>> dir(HelloWorld) ['HelloWorld', '_HelloWorld', '__builtins__', '__doc__', '__file__', '__name__', '_newclass', '_object', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic', 'new', 'new_instancemethod'] >>> ret = HelloWorld.HelloWorld(7) Hello World, Sunday! >>> print ret 7 非常好用吧。 题外话:关于Python的库链接的问题。 1. 在工程的属性设置里并没有指明要链接python24.lib,只是在整个VC的Library路径中有python24.lib所在的路径。这是怎么回事呢?注意pyconfig.h文件中的如下内容 /* For an MSVC DLL, we can nominate the .lib files used by extensions */ #ifdef MS_COREDLL # ifndef Py_BUILD_CORE /* not building the core - must be an ext */ # if defined(_MSC_VER) /* So MSVC users need not specify the .lib file in their Makefile (other compilers are generally taken care of by distutils.) */ # ifdef _DEBUG # pragma comment(lib,"python24_d.lib") # else # pragma comment(lib,"python24.lib") # endif /* _DEBUG */ # endif /* _MSC_VER */ # endif /* Py_BUILD_CORE */ #endif /* MS_COREDLL */ 凡是include了Python.h(其中又include了pyconfig.h)的文件在编译完成后的链接过程中都会去链接pragma comment(lib,"python24.lib")所指定的库。 2. 在运行时Python是需要python24.dll这个库文件的,但Python的安装目录里没有这个文件,其实在Python的安装过程中,其被拷贝到了C:/WINDOWS/system32目录里。 抱歉我太啰嗦了(生怕漏了什么,以后自己也忘记了),让大家见笑了。 顺便问一下,怎么贴附件呢?我想把VC的工程打包后贴进来,可行吗?三.简单例子
- 使用Swig封装C++到Python的心得--01
- 使用Swig封装的python对象
- 使用swig进行C/C++对Python的扩展
- Python调用C/C++(使用SWIG)
- SWIG封装C代码
- 使用SWIG将C++绑定到python
- 使用SWIG将C++绑定到python
- SWIG and Python(用SWIG将C/C++封装为Python扩展模块)
- swig 把c/c++ 封装成python可调用的so文动态链接库
- Python 使用C代码——swig
- 在Python中调用C++,使用SWIG
- 通过SWIG封装C/C++代码被Python调用
- swig的学习以及国密的python封装
- swig c python
- Python与C++,SWIG
- 用Swig封装C/C++
- 用Swig封装C/C++
- 使用SWIG和Python对C/C++进行单元测试(一)
- 进攻java(写下来的目标)
- TOMCAT下的JIVE2的中文问题分析及解决
- java swing的drag and drop源程序
- Heritrix架构学习笔记(二)
- JAVA调试技术--基础
- 使用Swig封装C++到Python的心得--01
- 字符检测程序(上) 检测GB2312、BIG5...
- 图片新闻实现
- InsideJVM(4)-Heap(堆)
- Heritrix架构学习笔记(三)
- jdbc桥连接数据库练习【1】
- SCJP认证套题解析之一
- 要分专业了
- 用 Python 的输入输出功能读取和写入数据