用python腳本寫應用比較方便,但有時候由於種種原因需要擴展python(比如給程序提供python接口等)。 之前一直想整理下,今天終於坐下來把這件事情給做了,這里記錄下,也方便我以后查閱。
說明: 測試環境中操作系統為CentOS6.5_x64,python版本為2.6
直接調用動態庫
1、編寫模塊動態庫文代碼
這里以求最大數為示例
代碼(callTest1.cpp)如下:
extern "C" { int Max(int i1,int i2) { return (i1>i2)?i1:i2; } }
在bash中執行以下命令:
g++ -fPIC -shared -o libcallTest1.so callTest1.cpp
生成動態庫文件libcallTest1.so
2、使用python調用動態庫
可以通過ctypes調用動態庫文件,具體如下:
#! /usr/bin/env python from ctypes import * import os so1 = CDLL(os.getcwd() + '/libcallTest1.so') print so1.Max(1,3)
使用boost庫擴展python
這種方式可以直接生成python模塊,使用import操作直接導入即可。 當然使用這種方式,需要安裝boost庫,具體操作這里就不說了,不懂的朋友自己查下。
boost官網:http://www.boost.org/
1、模塊代碼如下:
文件名:boostCallTest1.cpp
文件內容:
int Max(int i1,int i2) { return (i1>i2)?i1:i2; } #include <boost/python/module.hpp> #include <boost/python/def.hpp> using namespace boost::python; BOOST_PYTHON_MODULE(boostCallTest1) { def("Max",Max); }
2、編寫模塊編譯腳本
文件名: setup.py
文件內容:
#!/usr/bin/env python from distutils.core import setup from distutils.extension import Extension setup(name="PackageName", ext_modules=[ Extension("boostCallTest1", ["boostCallTest1.cpp"], libraries = ["boost_python"]) ])
3、編譯模塊並測試
編譯模塊:
python setup.py build
會在build目錄產生boostCallTest1.so文件,進入該目錄,可如下使用:
>>> import boostCallTest1
>>> boostCallTest1.Max(1,3)
3
使用swig擴展python
SWIG是個幫助使用C或者C++編寫的軟件能與其它各種高級編程語言進行嵌入聯接的開發工具。
SWIG能應用於各種不同類型的語言包括常用腳本編譯語言例如Perl, PHP, Python, Tcl, Ruby and PHP。
swig官網: http://www.swig.org/download.html
可以通過yum直接安裝:
yum install swig
1、編寫程序代碼
文件名:swigCall.cpp
內容如下:
int Max(int i1,int i2) { return (i1>i2)?i1:i2; }
2、編寫接口文件
文件名:swigCall.i
內容如下:
%module swigCall
%{
extern int Max(int i1,int i2);
%}
extern int Max(int i1,int i2);
3、編寫Makefile文件
內容如下:
all: make swigCall swigCall: swig -python -c++ swigCall.i g++ -c swigCall.cpp swigCall_wrap.cxx -I/usr/include/python2.7/ -fPIC g++ -shared swigCall.o swigCall_wrap.o -o _swigCall.so clean: rm -f swigCall_wrap.c* rm -f *.py* rm -f *.so rm -f *.o
注意:swig命令中要使用-c++參數編譯c++代碼
使用如下:
>>> import swigCall
>>> swigCall.Max(1,5)
5
>>>
使用SIP擴展python
SIP是從SWIG發展而來,專為Python調用C/C++模塊使用的。 注意,這里的SIP和voip中的sip不是同一個東西,這里的sip是擴展python用的,voip中的sip是一個通信協議,不要搞混了。
注意:
需要安裝python sip庫;
1、編寫c++模塊
1.1 編寫頭文件
文件名: sipCall.h 文件內容:
class TestMode { public: int Max(int i1,int i2); };
1.2 編寫模塊內容
文件名:sipCall.cpp 文件內容:
#include "sipCall.h" int TestMode::Max(int i1,int i2) { return (i1>i2)?i1:i2; }
2、編寫接口文件
文件名:sipCall.sip 文件內容:
%Module TestMode
class TestMode {
%TypeHeaderCode
#include "sipCall.h"
%End
public:
int Max(int i1,int i2);
};
3、生存靜態庫
這里用腳本實現,文件名稱:genlib.sh
文件內容:
#! /bin/bash
g++ -c -fPIC sipCall.cpp
ar -crs libsipCall.a sipCall.o
4、編寫configure文件
該腳本用於生成Makefile,內容如下:
#! /usr/bin/env python import os import sipconfig build_file = "sipCall.sbf" config = sipconfig.Configuration() cmd = " ".join([config.sip_bin, "-c", ".", "-b", build_file, "sipCall.sip"]) os.system(cmd) makefile = sipconfig.SIPModuleMakefile(config, build_file) makefile.extra_libs = ["sipCall"] makefile.LIBDIR.append(".") makefile.generate()
5、運行genlib.sh腳本生成lib文件;
6、運行configure.py腳本生成Makefile;
7、運行make生成模塊文件(so文件);
8、python測試如下:
>>> import TestMode
>>> dir(TestMode)
['TestMode', '__doc__', '__file__', '__name__', '__package__']
>>> s = TestMode.TestMode()
>>> s.Max(1,3)
3
本文github地址:
https://github.com/mike-zhang/mikeBlogEssays/blob/master/2015/20150808_用c++擴展python.md
歡迎補充