Python接口(2):使用ctpyes模块在python中调用c++代码
2017-02-20 14:07
831 查看
如何在Python中调用C/C++代码
How to mix C/C++ code in Python
本文介绍一种手动的、简单的在Python中使用C/C++代码的方式。这个方法主要使用了ctypes模块。其他的混合Python,C/C++编程的方法还有Swig 和 Boost.Python。前一种方法需要写一个接口文件(interface),而后一种需要使用庞大、深奥的boost类库,后两者适合可能适合更复杂的情况,这里只介绍第一种方法。
混合C/C++代码需要这几步:
1. 包装接口 C/C++ wrap functions up
2. 打包成共享库 Compiling C/C++ code and pack it to shared library
3. Python中导入共享库 Python imports shared library
先介绍一下背景,这里我的C++类GenomeSequence使用了模板(Template)和Memorymap,这是一个访问基因序列的类,比如如果一个生物序列是GAGTTTTATCGCTTCCATGACGCAGAAGTTAACACT… 我们的类是gs,那么gs[0] = ‘G’, gs[1]=’A’ …. 摘录相关的函数如下:
第二步是编译,记住单个C/C++文件编译时使用-fPIC参数,最后打包的时候编译成共享库,摘录Makefile文件中片段如下:
最后一步是在Python中写一个封装类,注意前两行引入ctypes库,之后就用这个库调用包装函数就行。
注意:我在GenomeSequence类的__getitem__中使用了如何扩展Python的容器类一文中介绍的一些技巧,这样可以更灵活的使用下标来访问数组中的元素。
fromctypes importcdll
lib=cdll.LoadLibrary("./libstatgen.so")
classGenomeSequence:
def__init__ (self):
self.obj=lib.GenomeSequence_new()
defopen(self, filename):
lib.GenomeSequence_setReferenceName(self.obj, filename)
def__len__ (self):
returnlib.GenomeSequence_getNumBase(self.obj)
def__getitem__(self, key):
ifisinstance(key,int):
returnchr(lib.GenomeSequence_getBase(self.obj, key))
elifisinstance(key,slice):
return''.join([self[x]forx inxrange(*key.indices(len(self)))])
elifisinstance(key,tuple):
return''.join([self[i]fori inkey])
defat(self, i):
returnchr(lib.GenomeSequence_getBase(self.obj, i))
defclose(self):
lib.GenomeSequence_close(self.obj)
if__name__ =='__main__':
gs=GenomeSequence ()
gs.open("/home/zhanxw/statgen/src/karma/test/phiX.fa");
printlen(gs)
seq=[(gs.at(i)) fori inxrange(60)]
print''.join(seq)
printgs[0:10],gs[20:30]
printgs[0:10,20:30]
printgs[-10:]
gs.close()
print"DONE"
本文主要参考【1】。这里的方法基本重复了【1】中的步骤。写出本文中的代码在于进一步验证ctypes库可以灵活的处理C/C++和Python中的简单数据类型int, char*。
【1】Calling C/C++ from python?
How to mix C/C++ code in Python
本文介绍一种手动的、简单的在Python中使用C/C++代码的方式。这个方法主要使用了ctypes模块。其他的混合Python,C/C++编程的方法还有Swig 和 Boost.Python。前一种方法需要写一个接口文件(interface),而后一种需要使用庞大、深奥的boost类库,后两者适合可能适合更复杂的情况,这里只介绍第一种方法。
混合C/C++代码需要这几步:
1. 包装接口 C/C++ wrap functions up
2. 打包成共享库 Compiling C/C++ code and pack it to shared library
3. Python中导入共享库 Python imports shared library
先介绍一下背景,这里我的C++类GenomeSequence使用了模板(Template)和Memorymap,这是一个访问基因序列的类,比如如果一个生物序列是GAGTTTTATCGCTTCCATGACGCAGAAGTTAACACT… 我们的类是gs,那么gs[0] = ‘G’, gs[1]=’A’ …. 摘录相关的函数如下:
class GenomeSequence : public genomeSequenceArray { public: /// Simple constructor - no implicit file open GenomeSequence(); /// set the reference name that will be used in open() /// \param referenceFilename the name of the reference fasta file to open /// \return false for success, true otherwise /// /// \sa open() bool setReferenceName(std::string referenceFilename); /// return the number of bases represented in this reference /// \return count of bases genomeIndex_t getNumberBases() const { return getElementCount(); } inline char operator[](genomeIndex_t index) const { uint8_t val; if (index < getNumberBases()) { if ((index&1)==0) { val = ((uint8_t *) data)[index>>1] & 0xf; } else { val = (((uint8_t *) data)[index>>1] & 0xf0) >> 4; } } else { val = baseNIndex; } val = isColorSpace() ? int2colorSpace[val] : int2base[val]; return val; } /* ........... more codes omitted ................ */ }
第二步是编译,记住单个C/C++文件编译时使用-fPIC参数,最后打包的时候编译成共享库,摘录Makefile文件中片段如下:
lib: g++ -c -fPIC -I./lib GenomeSequence_wrap.c g++ -shared -Wl,-soname,libstatgen.so -o libstatgen.so
最后一步是在Python中写一个封装类,注意前两行引入ctypes库,之后就用这个库调用包装函数就行。
注意:我在GenomeSequence类的__getitem__中使用了如何扩展Python的容器类一文中介绍的一些技巧,这样可以更灵活的使用下标来访问数组中的元素。
fromctypes importcdll
lib=cdll.LoadLibrary("./libstatgen.so")
classGenomeSequence:
def__init__ (self):
self.obj=lib.GenomeSequence_new()
defopen(self, filename):
lib.GenomeSequence_setReferenceName(self.obj, filename)
def__len__ (self):
returnlib.GenomeSequence_getNumBase(self.obj)
def__getitem__(self, key):
ifisinstance(key,int):
returnchr(lib.GenomeSequence_getBase(self.obj, key))
elifisinstance(key,slice):
return''.join([self[x]forx inxrange(*key.indices(len(self)))])
elifisinstance(key,tuple):
return''.join([self[i]fori inkey])
defat(self, i):
returnchr(lib.GenomeSequence_getBase(self.obj, i))
defclose(self):
lib.GenomeSequence_close(self.obj)
if__name__ =='__main__':
gs=GenomeSequence ()
gs.open("/home/zhanxw/statgen/src/karma/test/phiX.fa");
printlen(gs)
seq=[(gs.at(i)) fori inxrange(60)]
print''.join(seq)
printgs[0:10],gs[20:30]
printgs[0:10,20:30]
printgs[-10:]
gs.close()
print"DONE"
本文主要参考【1】。这里的方法基本重复了【1】中的步骤。写出本文中的代码在于进一步验证ctypes库可以灵活的处理C/C++和Python中的简单数据类型int, char*。
【1】Calling C/C++ from python?
相关文章推荐
- 使用boost.python在python调用C++接口(windows)
- 百度定制化图像开放平台使用--调用识别接口(python3代码)
- (原)python使用ctypes调用C/C++接口
- Linux使用Python调用C/C++接口
- Python 使用库ctypes调用C代码接口
- centos7下使用swig扩展python接口来调用c++ 实现声纹识别
- 使用swig在python中调用c++代码
- Python接口(1):使用Python调用C/C++的种种方法
- 使用SWIG实现Python调用C/C++代码
- linux 下python 调用C++ .so如何debug c++代码
- python调用C和C++代码
- Android JNI 使用的数据结构JNINativeMethod详解 ||建立Android SDK下的JNI、JAVA应用完整步骤---Android JAVA调用C++代码
- 使用JNI进行混合编程:在C/C++中调用Java代码
- java使用JNI调用C++代码(vs2010生成dll文件)
- linux 下python 调用C++ .so如何debug c++代码
- 使用JNI进行Java与C/C++语言混合编程(2)--在C/C++中调用Java代码
- 如何在C++代码中调用python代码(MinGW+Boost.Python)
- java调用C++代码-JNI的使用
- 使用JNI进行Java与C/C++语言混合编程(2)--在C/C++中调用Java代码
- 使用swig工具为go语言生成调用C、C++代码例子