c++ 代码 打包成python模块案例
本次使用cython模块把一个已经用c++实现好了的库包装成python的一个模块。
案例目录结构
├── rectangle
│ ├── Rectangle.cpp
│ └── Rectangle.h
├── rect.pxd
├── rect.pyx
└── setup.py
- rectangle目录是c++源码
- 外层目录是python模块代码
c++原代码
- Rectangle.h file
#ifndef RECTANGLE_H
#define RECTANGLE_H
namespace shape{
class Rectangle{
public:
int x0,y0,x1,y1;
Rectangle();
Rectangle(int x0,int y0,int x1, int y1);
~Rectangle();
int getArea();
void getSize(int * width, int * height);
void move(int dx, int dy);
};
}
#endif
- Rectangle.cpp file
#include<assert.h>
#include"Rectangle.h"
namespace shape{
Rectangle::Rectangle(int x0,int y0,int x1,int y1):x0(x0),y0(y0),x1(x1),y1(y1){}
Rectangle::Rectangle(){}
int Rectangle::getArea()
{
return (x0 - x1) * (y0 - y1);
}
void Rectangle::getSize(int * width,int * height)
{
assert(width != nullptr && height != nullptr);
*width = x1 - x0;
*height = y1 - y0;
}
Rectangle::~Rectangle(){}
void Rectangle::move(int dx,int dy)
{
x1 += dx;
x0 += dx;
y1 += dy;
y0 += dy;
}
}
cython 包装
- cython 包装需要写两个文件
.pyx
和.pxd
文件,.pxd
文件相当于头文件,声明你需要调用到的函数、变量、类等,因为cython不会去解析cpp的.h头文件,所以需要用.pxd
文件声明一下。
rect.pxd代码
cdef extern from "Rectangle.h" namespace "shape":
cdef cppclass Rectangle:
Rectangle() except +
Rectangle(int,int,int,int) except +
int x0,y0,x1,y1
int getArea()
void getSize(int *width,int *height)
void move(int,int)
- 这里
except +
作用是把c++ 代码中异常传递出来 - 这些声明基本和c++头文件差不多
rect.pyx代码
cimport rect # 导入上面写的rect.pxd 文件
cdef class Rectangle: #定义一个python类
cdef rect.Rectangle _rect #因为pxd文件声明过,这里可以使用Rectagnle这c++类
def __cinit__(self,x0,y0,x1,y1):
self._rect = rect.Rectangle(x0,y0,x1,y1)
def get_area(self):
return self._rect.getArea()
def get_size(self):
cdef int width,height;
self._rect.getSize(&width,&height)
return width,height
def move(self,dx,dy):
self._rect.move(dx,dy)
#属性访问
@property
def x0(self):
@x0.setter
def x0(self,x0):
self._rect.x0 = x0
@property
def x1(self):
return self._rect.x1
@x1.setter
def x1(self, x1):
self._rect.x1 = x1
@property
def y0(self):
return self._rect.y0
@y0.setter
def y0(self, y0):
self._rect.y0 = y0
@property
def y1(self):
return self._rect.y1
@y1.setter
def y1(self, y1):
self._rect.y1 = y1
setup.py代码
from distutils.core import setup,Extension
from Cython.Build import cythonize
ext = Extension("Rectangle",
sources=["rect.pyx","rectangle/Rectangle.cpp"],
include_dirs=["rectangle"], # c++的头文件目录
language="c++"
)
setup(ext_modules=cythonize(ext))
编译
python setup.py build_ext --inplace
编译成功后会直接在当前目录下生成一个库文件
或者使用 python setup.py build
进行编译
python setup.py install
进行安装,然后全局就可以使用这个模块了。
代码获取链接
https://download.csdn.net/download/weixin_42081309/11834279