前言
官方的Python是由C语言编写,所以就像我之前发布的文章那样,Python可以调用动态链接库(在Windows中是dll格式)实现通过Python执行C代码逻辑。但dll的弊端在于,导出类型应该为c类型,但凡涉及字符串或者数组,你就要使用指针,而且要在写Python中写显示调用的代码,还是设置指针类型,这无疑增加了使用者的难度。另外,你使用C语言这样的中级语言编写代码,也会让你有巧妇难为无米之炊的感觉。
我们知道,pyd模块(Windows平台下是pyd,Linux平台是so)是python的扩展库模块文件,是可以通过其他语言编写的专给Python用的二进制文件。调用pyd相比调用dll可方便不少。
然而直接编写pyd模块,就需要了解Python的底层逻辑,了解PyObject也有一定的学习成本,而且编写时候也离不开指针,需要自己转换成PyObject类型以及异常处理。
不过,随着Cyton的引入大大方便了pyd的编写,你只管实现逻辑,至于怎么转换成Python类型交给Cython。不过个人认为Cython最牛逼的一点是对c++的支持。
官方文档地址(建议先看我的教程在看官方文档,不然容易看不懂):
在开始之前别忘了装Cython模块:
pip install cython
编写步骤
1.了解C++和Python之间的转换类型
pyd本质就是做一个或者多个导出函数或者类给Python调用(导出自定义c++类我们不讲,这个在官方文档有详细介绍,我只讲常用的易上手的和官方不怎么涉及的)那么,导出函数的参数类型,返回值类型就需要规范一下。这个具体的细节我们后续在说。先了解一下这个图。
2.编写C++代码:
我们需要编写实现逻辑的c++代码,我这里以一个字符串分割函数(split为例):
splitcp.h
#include <string>
#include <vector>
using namespace std;
vector<string> split(string s, string sep);//声明一个函数
不废话,直接使用这种vector<string>这种复杂类型。其他教程用double,int类型函数,那真的鸡肋。没有实际意义,看完都不知道这种vector<string>复杂类型怎么处理。
需要的头文件,命名空间都在头文件中定义,cpp文件只引用头文件。(个人习惯,不强制要求)
splitcp.cpp
#include "splitcp.h"
vector<string> split(string s, string sep) {
vector<string> result;
size_t start = 0;
size_t sep_len = sep.size();
size_t pos;
while (true) {
pos = s.find(sep, start);
if (pos == s.npos) {
result.push_back(s.substr(start));
break;
}
result.push_back(s.substr(start, pos - start));
start = pos + sep_len;
}
return result;
}
编写完代码后要进行测试,先保证能在c++环境中成功运行。
int main() {
string a = "你好,,世界,,this ,is,,c++";
string sp = ",,";
auto res = split(a, sp);
for (auto& i : res) {
cout << i << endl;
}
}
测试通过,说明咱们写的代码没毛病,那么接下来就可以编写Cython配置文件了。
3.编写Cython导入文件pxd
这一步最复杂也最容易出错,希望朋友们仔细阅读,因为Cython配置文件不像写代码,还有VS等IDE软件给你错误