Python调用C/C++(使用SWIG)
2017-09-13 15:59
1051 查看
这里选用SWIG的一个重要原因是,它不仅可以用于Python,也可以用于其他语言。如今SWIG已经支持C/C++的好基友Java,主流脚本语言Python、Perl、Ruby、PHP、JavaScript、tcl、Lua,还有Go、C#,以及R。
2、 解压 .zip 文件到目录,比如:C:\
3、 添加环境变量到path, 比如: C:\swigwin
4、 简单测试安装是否成功:
打开Dos,在命令行执行: swig –help, 显示 Target Language Options即表明安装成功。
如果是使用C源码,则选项:
这样会创建两个不同的文件:example_wrap.cxx(如果用c源码是example_wrap.c),和python文件example.py。
注:swig生成的扩展模块对象名必须使用python模块名并在前面加上下划线_,刚才我们通过swig生成的python文件是example.py,所以这里的模块对象名必须是’_example’,否则无法顺利编译。
include_dirs指定了搜索的头文件路径,library_dirs指定了搜索的动态库或者静态库的路径
注意如果路径中包含空格如Program Files,要用简写形式去除空格如Progra~1
会在本目录下生成_example.pyd模块。
打开GCLinkage.h定位问题如下:
_MSC_VER这个相当于做了宏的检测 _MSC_VER 定义编译器的版本。下面是一些编译器版本的_MSC_VER值:
MS VC++ 14.0 _MSC_VER = 1900 vs2015
MS VC++ 12.0 _MSC_VER = 1800 vs2013的编译器他的平台是v120
MS VC++ 11.0 _MSC_VER = 1700 vs2012的编译器他的平台是v110
MS VC++ 10.0 _MSC_VER = 1600 Visual C++ 2010
MS VC++ 9.0 _MSC_VER = 1500 Visual C++ 2008
MS VC++ 8.0 _MSC_VER = 1400 Visual C++ 2005
MS VC++ 7.1 _MSC_VER = 1310
MS VC++ 7.0 _MSC_VER = 1300
MS VC++ 6.0 _MSC_VER = 1200
MS VC++ 5.0 _MSC_VER = 1100
检测到“_MSC_VER”的不匹配项: 值“1900”不匹配最高值“1700”
原因:由于使用了vs2015,而源文件中只支持到vs2012
怎么看python使用的是哪个版本的vs?
cmd中执行python,输出:
python输出版本信息中就有
修改为:
保存,再次运行python setup.py build,成功启动编译,最后在链接阶段报错,提示找不到库文件ucrt.lib
这个ucrt.lib是Visual C++ 2015对C语言运行库进行重构后的产物,对应以前版本Visual C++中的msvcrt.lib,解决的办法也很简单,打开VC安装目录/lib,找到msvcrt.lib,复制一份并更名为ucrt.lib,再次运行python setup.py build,编译成功。
You are mixing code that was compiled with /MD (use DLL version of CRT) with code that was compiled with /MT (use static CRT library). That cannot work, all source code files must be compiled with the same setting. Given that you use libraries that were pre-compiled with /MD, almost always the correct setting, you must compile your own code with this setting as well.
在VS中可以用以下方法设置:
但是python的解决方法找了很久没有找到,只好还是在_msvccompiler.py中修改。可以看到,执行编译的命令行中部分信息如下:
这里默认是/MT模式的。
在_msvccompiler.py找到这一行:
修改为:
保存后,终于编译成功!
注:如果导入模块失败,需要将模块所在路径添加到sys.path中,在次导入就会成功
参考:
SWIG实现python对c++封装
SWIG官方说明文档
python的setup.py文件
python官方说明Packaging and Distributing Projects
一、SWIG环境搭建
1、 下载Swig for Windows:http://www.swig.org/download.html2、 解压 .zip 文件到目录,比如:C:\
3、 添加环境变量到path, 比如: C:\swigwin
4、 简单测试安装是否成功:
打开Dos,在命令行执行: swig –help, 显示 Target Language Options即表明安装成功。
二、以c++为例
1、编写c++源文件
//example.h #include <iostream> using namespace std; class Example{ public: void say_hello(); }; //example.cpp #include "example.h" void Example::say_hello() { printf("hello"); }
2、再写一个swig模块定义文件如下
%module example %{ #include "example.h" %} %include "example.h"
3、通过命令行运行:
$ swig -python -c++ example.i
如果是使用C源码,则选项:
$ swig -Python example.i
这样会创建两个不同的文件:example_wrap.cxx(如果用c源码是example_wrap.c),和python文件example.py。
4、使用python.distutils生成模块动态库
python自带一个distutils工具,可以用它来创建python的扩展模块。使用它也很简单,只需要先定义一个配置文件,通常是命名为setup.py,如下:#!/usr/bin/env python """ setup.py file for SWIG C\+\+/Python example """ from distutils.core import setup, Extension example_module = Extension('_example', sources=['example.cpp', 'example_wrap.cxx',]) setup (name = 'example', version = '0.1', author = "www", description = """Simple swig C\+\+/Python example""", ext_modules = [example_module], py_modules = ["example"], )
注:swig生成的扩展模块对象名必须使用python模块名并在前面加上下划线_,刚才我们通过swig生成的python文件是example.py,所以这里的模块对象名必须是’_example’,否则无法顺利编译。
为setup.py添加c/c++ 头文件或者库的搜索路径
通过上网查询,得知,setup.py的ext_modules参数的详细解释,所以,只用在Extension中加上两个参数,如下:example_module = Extension('_example', sources=['example.cpp', 'example_wrap.cxx',], include_dirs = ['C:\Progra~1\API','C:\Progra~1\include'], library_dirs = ['C:\Progra~1\API\x64','C:\Progra~1\lib\Win32_i86'] )
include_dirs指定了搜索的头文件路径,library_dirs指定了搜索的动态库或者静态库的路径
注意如果路径中包含空格如Program Files,要用简写形式去除空格如Progra~1
5、编译
命令行中将当前工作目录切换到文件example.cpp,example_wrap.cxx,example.py,setup.py所在的目录,然后输入以下命令:python setup.py build_ext --inplace
会在本目录下生成_example.pyd模块。
问题1:检测到“_MSC_VER”的不匹配项问题
打开GCLinkage.h定位问题如下:
_MSC_VER这个相当于做了宏的检测 _MSC_VER 定义编译器的版本。下面是一些编译器版本的_MSC_VER值:
MS VC++ 14.0 _MSC_VER = 1900 vs2015
MS VC++ 12.0 _MSC_VER = 1800 vs2013的编译器他的平台是v120
MS VC++ 11.0 _MSC_VER = 1700 vs2012的编译器他的平台是v110
MS VC++ 10.0 _MSC_VER = 1600 Visual C++ 2010
MS VC++ 9.0 _MSC_VER = 1500 Visual C++ 2008
MS VC++ 8.0 _MSC_VER = 1400 Visual C++ 2005
MS VC++ 7.1 _MSC_VER = 1310
MS VC++ 7.0 _MSC_VER = 1300
MS VC++ 6.0 _MSC_VER = 1200
MS VC++ 5.0 _MSC_VER = 1100
检测到“_MSC_VER”的不匹配项: 值“1900”不匹配最高值“1700”
原因:由于使用了vs2015,而源文件中只支持到vs2012
怎么看python使用的是哪个版本的vs?
cmd中执行python,输出:
python输出版本信息中就有
MSC v.1900 64 bit (AMD64)
解决方法
编辑Python安装目录/Lib/distutils/_msvccompiler.py(我这里是C:\Users\username\AppData\Local\Programs\Python\Python35\Lib\distutils),搜索这一行:if version >= 14 and version > best_version:
修改为:
if version == 11 and version > best_version:
保存,再次运行python setup.py build,成功启动编译,最后在链接阶段报错,提示找不到库文件ucrt.lib
这个ucrt.lib是Visual C++ 2015对C语言运行库进行重构后的产物,对应以前版本Visual C++中的msvcrt.lib,解决的办法也很简单,打开VC安装目录/lib,找到msvcrt.lib,复制一份并更名为ucrt.lib,再次运行python setup.py build,编译成功。
问题2:LIBCMT.lib(memcpy.obj) : error LNK2005: memmove 已经在 ucrt.lib(MSVCR110D.dll)中定义
从error LNK2005得知:You are mixing code that was compiled with /MD (use DLL version of CRT) with code that was compiled with /MT (use static CRT library). That cannot work, all source code files must be compiled with the same setting. Given that you use libraries that were pre-compiled with /MD, almost always the correct setting, you must compile your own code with this setting as well.
在VS中可以用以下方法设置:
但是python的解决方法找了很久没有找到,只好还是在_msvccompiler.py中修改。可以看到,执行编译的命令行中部分信息如下:
>python example_setup.py build_ext --inplace running build_ext building '_example' extension C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\BIN\x86_amd64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MT ......
这里默认是/MT模式的。
在_msvccompiler.py找到这一行:
self.compile_options.append('/MD' if self._vcruntime_redist else '/MT')
修改为:
self.compile_options.append('/MD')
保存后,终于编译成功!
6、测试
import examlpe example.Example().say_hello()
注:如果导入模块失败,需要将模块所在路径添加到sys.path中,在次导入就会成功
参考:
SWIG实现python对c++封装
SWIG官方说明文档
python的setup.py文件
python官方说明Packaging and Distributing Projects
相关文章推荐
- centos中使用swig实现python调用c++
- 使用swig在python中调用c++代码
- 使用SWIG实现Python调用C/C++代码
- linux下使用swig让python调用C++(复杂版:包括多文件调用和链接库)
- Python调用C++函数(SWIG,VS2013使用numpy.i完成Numpy与C++数组转换)
- linux下使用SWIG实现Python调用C++ sdk读取相机图片
- centos7下使用swig扩展python接口来调用c++ 实现声纹识别
- Windows下python使用SWIG调用C++ dll
- linux下使用swig让python调用C++(复杂版:包括多文件调用和链接库)
- Linux下利用SWIG完成Python对使用OpenCV的C++文件的调用
- 在Python中调用C++,使用SWIG
- 使用swig从c/c++代码生成java/python/R/php...代码
- 通过SWIG封装C/C++代码被Python调用
- Linux使用Python调用C/C++接口
- 使用swig实现C++的python扩展功能
- c++生成dll使用python调用dll的方法
- 使用SWIG和Python对C/C++进行单元测试(一)
- 使用SWIG实现C/C++与其他语言间的互相调用 zz
- 使用SWIG实现C/C++与其他语言间的互相调用
- c++生成dll使用python调用dll的方法