Python3.X使用Cython调用C/C++
1 创建C++代码
假设我们需要让Python调用的C++代码如下(文件名为demo.h
):
#ifndef DEMO_H #define DEMO_H using namespace std; namespace demo { class MyDemo { public: int a; MyDemo(); MyDemo(int a ); ~MyDemo(); int mul(int m ); int add(int b); void sayHello(char* name); }; } #endif
对应的C++实现代码如下(demo.cpp):
#include "demo.h" #include <iostream> namespace demo { MyDemo::MyDemo () {} MyDemo::MyDemo (int a) { this->a = a; } MyDemo::~MyDemo () {} int MyDemo::mul(int m) { return this->a*m; } int MyDemo::add (int b) { return this->a+b; } void MyDemo::sayHello(char* name){ cout<<"hello "<<name<<"!"<<endl; } }
2 编写pxd文件
pxd 文件可以看成是Cython(即pyx文件)的头文件,关于pxd和pyx文件可以简单如下来理解:
pxd文件是pyx与C/C++之间的桥梁。
pyx是C/C++与Python之间的桥梁。
既然pxd是头文件,那就是跟demo.h长的很像,创建cdemo.pxd文件,内容如下。
cdef extern from "demo.cpp": pass # Decalre the class with cdef cdef extern from "demo.h" namespace "demo": cdef cppclass MyDemo: MyDemo() except + MyDemo(int) except + int a int mul(int ) int add(int ) void sayHello(char*)
3 编写pyx文件
前面说过,pyx文件是C/C++与Python之间的桥梁,也就是pyx文件会将C/C++代码做一层包装,方便Python直接调用,创建adapter.pyx文件,代码如下。
# distutils: language = c++ from cdemo cimport MyDemo # Create a Cython extension type which holds a C++ instance # as an attribute and create a bunch of forwarding methods # Python extension type. cdef class PyMyDemo: cdef MyDemo c_mydemo # Hold a C++ instance which we're wrapping def __cinit__(self,a): self.c_mydemo = MyDemo(a) def mul(self, m): return self.c_mydemo.mul(m) def add(self,b): return self.c_mydemo.add(b) def sayHello(self,name ): self.c_mydemo.sayHello(name)
其中,第一行# distutils: language = c++会指定当前文件生成C++文件。创建PyMyDemo类用于将C/C++代码做一层封装,使得Python能直接调用。
4 创建setup.py文件
setup.py文件相对比较简单,代码如下。
from distutils.core import setup from Cython.Build import cythonize setup(ext_modules=cythonize("adapter.pyx"))
5 执行编译
在控制台输入如下命令:
python setup.py build_ext --inplace
执行命令后,在当前目录会生成adapter.cpp,这个文件是根据adapter.pyx生成的。同时还会生成adapter.cp36-win_amd64.pyd文件(Linux环境下对应so文件)。 这里的pyd文件是windows平台对应文件,这就是我们需要的文件。
6 测试
测试结果如下
>>> from adapter import PyMyDemo >>> demo=PyMyDemo(2) >>> demo.add(1) 3 >>> demo.mul(2) 4 >>> demo.sayHello(b'HuaChao') hello HuaChao!