python调用C函数(Python扩展)

方法介绍

Python是著名的胶水语言,顾名思义“胶水”的作用就是黏合,哪里需要黏哪里。Python就是可以将各种语言写的模块粘合成为一个完整的程序,这样可以充分发挥各语言的优势。其中比较常见的应用就是Python先实现程序外在的UI界面,之后再调用C语言所实现的程序內部运算逻辑模块。
在Python程序中调用C/C++编写的库,专业术语叫做Python扩展,主要就是为了提升逻辑核心关键代码的性能。

四种方法

常用的四种扩展方法:
ctypes、CFFI、Cython、SWIG

方法操作速度
ctypes调用动态链接库
CFFI
CythonPython编译成C,C再编译为.pyd文件,Python可直接调用
SWIGC代码封装成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.libpython36.lib,并注释掉#define Py_DEBUG
  • 还是要注意x86对应的是Python32位解释器
  • SWIG Windows 官方下载地址解压就能用,编译命令在命令行下写就可以
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值