方法介绍
Python是著名的胶水语言,顾名思义“胶水”的作用就是黏合,哪里需要黏哪里。Python就是可以将各种语言写的模块粘合成为一个完整的程序,这样可以充分发挥各语言的优势。其中比较常见的应用就是Python先实现程序外在的UI界面,之后再调用C语言所实现的程序內部运算逻辑模块。
在Python程序中调用C/C++编写的库,专业术语叫做Python扩展,主要就是为了提升逻辑核心关键代码的性能。
四种方法
常用的四种扩展方法:
ctypes、CFFI、Cython、SWIG
方法 | 操作 | 速度 |
---|---|---|
ctypes | 调用动态链接库 | 慢 |
CFFI | 慢 | |
Cython | Python编译成C,C再编译为.pyd文件,Python可直接调用 | 快 |
SWIG | C代码封装成python代码 | 快 |
正确的做法就是
全部写成ctypes,或者cffi,送上线跑,有空再把最慢的一两个接口换成cython
——知乎用户韦易笑
本文所有实验都是基于Windows操作系统,LInux下的扩展很简单方便,网上也有很多实例就不赘述了。
1.ctypes调用动态链接库
1.1操作方法
- 步骤一:生成DLL
在Windows下最好的C/C++IDE——VS生成,具体代码如下:
头文件:“DLL.h”
#pragma once
__declspec(dllexport) int add(int a, int b);
源文件:“DLL.c”
#include"DLL.h"
int add(int a,int b) {
return a+b;
}
- 步骤二:使用ctypes调用DLL
“ctypes_demo.py”
from ctypes import *
lib = CDLL('C_DLL_demo')
print(lib.add(2,3))
注:要将步骤一生成的.dll文件和.lib文件放在ctypes_demo.py的同一目录下
1.2注意
- 遇到的问题1:OSError: [WinError 193] %1 is not a valid Win32 application
DLL是32位程序,如果Python解释器是64位就会引起该错误,不可以32位和64位混合。
解决方案:是用32位解释器解释Python程序。 - 遇到的问题2:TypeError: ‘str’ object is not callable
要确保源文件是C编译器进行便,如果是C++ 编译器编译,编译结束后函数名字会发生改变,进而引起此错误。
解决方案:生成DLL时,使用.c(纯C)文件,如果是.cpp文件就在头文件导出函数前面中加入extern "C"
。
2.SWIG
2.1操做方法
- 步骤一:使用VS创建一个空项目,编写C语言程序
“example.c”
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n - 1);
}
int my_mod(int x, int y) {
return (x%y);
}
- 步骤二:编写接口文件,该文件作为SWIG的输入
“example.i”
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
- 步骤三:接口文件输入到SWIG,编译为包裹文件filename_wrap.c,并且生成Python module(还不能直接导入),名字为filename.py
SWIG编译命令如下:
swig -python example.i
会得到两个文件
-
步骤四:配置动态链接库环境,生成 .pyd文件
首先修改工程属性,修改目标文件名为_filename(本例为_example),目标文件扩展名为 .pyd,配置类型修改为dll;
其次修改工程的包含目录和库目录,路径分别设置为32位Python解释器的include文件夹和libs文件夹;
最后修改命令行,在其他选项中增加一个/wd4996。
就这几个红框框里就有不一一截图了 -
步骤五:生成解决方案(ctrl+shift+B),就会得到.pyd文件
-
步骤六:把pyd文件和py模块文件都放在要扩展的Python目录下
-
步骤六:调用
import example
print(example.fact(5))
print(example.my_mod(6,4))
2.2注意
- 遇到的问题1:链接错误,fatal error LNK1104 无法打开 python36_d.lib
可能还是Windows系统的坑,或者Debug模式下的问题
解决方案:找到解释器目录下的pyconfig.h ,修改python36_d.lib
为python36.lib
,并注释掉#define Py_DEBUG
- 还是要注意x86对应的是Python32位解释器
- SWIG Windows 官方下载地址解压就能用,编译命令在命令行下写就可以