Cython之python编译so

cython简介

  • Cython是一个编程语言,它通过类似Python的语法来编写C扩展并可以被Python调用.既具备了Python快速开发的特点,又可以让代码运行起来像C一样快,同时还可以方便地调用C library。

  • Cython函数运行速度回避python快很多。

安装Cython

cython需要先安装gcc,这里略过

安装cython

pip install cython

实例

测试程序

新建test.py

import datetime
 
class Today():
    def get_time(self):
        print(datetime.datetime.now())
 
    def say(self):
        print("hello from JC!")

加密脚本

新建加密脚本setup.py

from distutils.core import setup
from Cython.Build import cythonize
 

setup(ext_modules = cythonize(["test.py"]))

也可以打包多个文件为so例如:

ext_modules=cythonize(["Student.py", "for_call.py"]),
ext_modules = cythonize([r'core/*.pyx', r'*.pyx'], annotate=True)

测试代码

新建测试代码so_test.py

from test import Today
 
t = Today()
t.get_time()
t.say()

测试

python3 so_test.py
python3 setup.py build_ext

生成了test.c文件以及build,build里面是动态库

删除test.py验证

root@ubuntu:/home/xzw/cython# rm test.py 

root@ubuntu:/home/xzw/cython# cp build/lib.linux-x86_64-3.6/test.cpython-36m-x86_64-linux-gnu.so ./

root@ubuntu:/home/xzw/cython# ls
build  __pycache__  setup.py  so_test.py  test.c  test.cpython-36m-x86_64-linux-gnu.so

root@ubuntu:/home/xzw/cython# python3 so_test.py
2022-01-21 03:22:34.089421
hello from JC!

root@ubuntu:/home/xzw/cython# mv test.cpython-36m-x86_64-linux-gnu.so test.so

root@ubuntu:/home/xzw/cython# python3 so_test.py
2022-01-21 03:22:45.146438
hello from JC!

使用Cython调用C/C++

创建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

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;
    }
}

编写pxd文件

pxd 文件可以看成是Cython(即pyx文件)的头文件,关于pxdpyx文件可以简单如下来理解:

pxd文件是Python与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*)

编写pyx文件

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++文件。

创建setup

setup.py文件相对比较简单


from distutils.core import setup

from Cython.Build import cythonize

setup(ext_modules=cythonize("adapter.pyx"))

执行编译

python setup.py build_ext --inplace

执行命令后,在当前目录会生成adapter.cpp,这个文件是根据adapter.pyx生成的。同时还会生成adapter.cp36-win_amd64.pyd文件(Linux环境下对应so文件)。 这里的pyd文件是windows平台对应文件,这就是我们需要的文件。

测试

>>> from adapter import PyMyDemo
>>> demo=PyMyDemo(2)
>>> demo.add(1)
3
>>> demo.mul(2)
4
>>> demo.sayHello(b'HuaChao')
hello HuaChao!

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×