当前位置: 首页 > news >正文

Python中使用C扩展详解

文章目录

      • 1. Python/C API
      • 示例
      • 2. Cython
      • 示例
      • 3. ctypes
      • 关于C扩展的进一步讨论
        • 安全性和兼容性
        • 性能优化策略
        • 调试C扩展
        • 发布和分发C扩展
      • 应用实例:加速矩阵乘法运算
        • 1. 准备C扩展代码
        • 2. 编译C扩展
        • 3. 在Python中使用C扩展

在Python中,使用C扩展是一种提高程序性能、访问底层系统资源或复用现有C代码的方法。Python提供了几个库和工具来帮助开发者编写、编译和加载C扩展模块,最常用的有 Python/C APICythonctypes

1. Python/C API

Python/C API允许你直接用C语言编写Python模块。这意味着你可以创建新的数据类型、定义函数,并直接与Python解释器交互。使用API的一般步骤包括:

  • 编写C代码实现功能。
  • 使用API定义Python类型的对象和方法。
  • 编译C代码为共享库(.so文件)。
  • 在Python中通过import语句加载这个库。

示例

一个简单的C扩展模块示例,该模块提供一个函数计算两个整数的和:

// example.c
#include <Python.h>static PyObject* example_add(PyObject* self, PyObject* args) {int a, b;if (!PyArg_ParseTuple(args, "ii", &a, &b)) {return NULL;}return Py_BuildValue("i", a + b);
}static PyMethodDef ExampleMethods[] = {{"add", (PyCFunction)example_add, METH_VARARGS, "Add two numbers"},{NULL, NULL, 0, NULL}
};static struct PyModuleDef examplemodule = {PyModuleDef_HEAD_INIT,"example",   /* name of module */NULL,       /* module documentation, may be NULL */-1,         /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ExampleMethods
};PyMODINIT_FUNC PyInit_example(void) {return PyModule_Create(&examplemodule);
}

编译此代码需要使用Python的开发头文件和库,通常命令如下(假设已安装Python开发包):

gcc -shared -o example.so -I/usr/include/python3.x example.c -lpython3.x

然后在Python中导入这个模块:

import example
print(example.add(1, 2))

2. Cython

Cython是一个更高级的工具,它允许你用类似Python的语法编写代码,然后将其编译成C扩展。Cython添加了静态类型声明,从而能够更高效地调用C库和执行操作。使用Cython,通常涉及以下步骤:

  • 安装Cython。
  • 编写.pyx文件,其中可以混合Python和C类型的注解。
  • 使用Cython编译器生成C代码。
  • 编译生成的C代码到共享库。
  • 在Python中导入这个库。

示例

Cython版本的上述示例:

# example.pyx
def add(int a, int b):return a + b

使用Cython编译并使用这个模块,首先安装Cython(如果尚未安装):

pip install cython

然后编译example.pyx文件:

cythonize -3 -i example.pyx

这将生成一个可以直接在Python中导入的共享库文件。之后在Python中使用:

import example
print(example.add(1, 2))

3. ctypes

ctypes是Python标准库的一部分,它提供了一个更灵活但可能更复杂的途径来调用C库中的函数,而不需要预先编译C代码。你直接在Python中定义C数据类型和函数原型,然后加载动态链接库。

选择哪种方式取决于你的具体需求:如果追求极致性能且不介意更复杂的开发流程,直接使用Python/C APICython可能是最佳选择;如果你只是想简单地调用现有的C库函数,ctypes可能更合适。每种方法都有其优势和适用场景,关键在于权衡开发效率、维护成本和性能需求。

关于C扩展的进一步讨论

安全性和兼容性
  • 安全性:直接使用C扩展时,需要格外小心内存管理和其他潜在的错误,因为C语言不会自动处理这些错误,而Python则设计得更为健壮。使用Cython可以在一定程度上减少这类问题,因为它提供了更多的错误检查。
  • 兼容性:C扩展通常需要针对特定的Python版本编译。这意味着如果你的扩展需要在不同Python版本上运行,可能需要为每个版本分别编译。Cython和Python/C API都提供了宏和条件编译功能来帮助处理兼容性问题。
性能优化策略
  • 减少Python/C切换开销:在编写C扩展时,尽量减少从Python环境到C环境的转换次数。例如,在循环中避免频繁调用Python API。
  • 使用缓冲区协议:对于大量数据处理,利用Python的缓冲区协议(buffer protocol)可以更高效地处理数组和缓冲区数据,避免复制。
  • 多线程和异步:虽然C扩展可以直接使用多线程,但需要注意全局解释器锁(GIL)。对于CPU密集型任务,考虑使用子进程或者结合Python的异步IO功能。
调试C扩展

调试C扩展比调试纯Python代码要复杂一些,但也有相应的工具可用:

  • gdb:GNU调试器,可以用来调试C代码。当你的扩展崩溃或行为异常时,gdb可以帮助定位问题。
  • Cython调试:如果使用Cython,可以在编译时开启调试信息,然后使用gdb或IDE的调试功能。
  • Python的faulthandler模块:可以在Python程序崩溃时输出堆栈跟踪,帮助识别问题所在。
发布和分发C扩展
  • 预编译二进制包:为了便于用户安装,可以为常见的操作系统和Python版本预编译二进制包。
  • 使用CMake或Setuptools:这些工具可以帮助自动化编译过程,使得安装过程对用户更加友好。特别是SetuptoolsExtension类可以用来指定C扩展的编译选项,并自动构建。

C扩展是提升Python应用性能的有效手段,尤其是在处理高性能计算、密集运算或硬件交互等场景。正确使用这些技术,结合良好的编程实践和调试技巧,可以极大地增强Python应用的能力。不过,由于其增加了开发和维护的复杂度,因此在决定是否采用C扩展前,应当仔细评估性能提升与额外工作量之间的平衡。

应用实例:加速矩阵乘法运算

假设我们有一个应用场景,需要频繁进行大规模矩阵乘法运算,而Python原生的矩阵乘法可能无法满足性能要求。这时,通过编写C扩展来加速这一过程是一个不错的选择。这里以使用Python/C API为例,展示如何实现这一优化。

1. 准备C扩展代码

首先,我们编写C代码来实现矩阵乘法。这个C函数将接收两个二维数组(矩阵),计算它们的乘积,并返回结果矩阵。

// matrix_multiply.c
#include <Python.h>void matmul(int n, double* A, double* B, double* C) {for(int i = 0; i < n; ++i) {for(int j = 0; j < n; ++j) {double sum = 0;for(int k = 0; k < n; ++k) {sum += A[i*n+k] * B[k*n+j];}C[i*n+j] = sum;}}
}static PyObject* py_matrix_multiply(PyObject* self, PyObject* args) {int n;PyObject* py_A, *py_B;double* A, *B, *C;// 解析输入参数if (!PyArg_ParseTuple(args, "O!O!i", &PyArray_Type, &py_A, &PyArray_Type, &py_B, &n)) {return NULL;}// 确保输入是二维数组且元素类型为doubleif (PyArray_NDIM(py_A) != 2 || PyArray_NDIM(py_B) != 2 ||PyArray_TYPE((PyObject*)py_A) != NPY_DOUBLE ||PyArray_TYPE((PyObject*)py_B) != NPY_DOUBLE) {PyErr_SetString(PyExc_TypeError, "Input arrays must be 2D and of type double.");return NULL;}// 获取数据指针A = (double*)PyArray_DATA(py_A);B = (double*)PyArray_DATA(py_B);C = (double*)malloc(n*n*sizeof(double));// 执行矩阵乘法matmul(n, A, B, C);// 创建并返回结果numpy数组PyObject* result = PyArray_SimpleNewFromData(2, &n, NPY_DOUBLE, (void*)C);Py_INCREF(result); // 增加引用计数,防止数据被提前释放return result;
}static PyMethodDef MatrixMethods[] = {{"matrix_multiply", py_matrix_multiply, METH_VARARGS, "Multiply two matrices."},{NULL, NULL, 0, NULL}
};// 模块初始化
static struct PyModuleDef matrix_module = {PyModuleDef_HEAD_INIT,"matrix_extension",NULL,-1,MatrixMethods
};PyMODINIT_FUNC PyInit_matrix_extension(void) {import_array(); // 初始化numpy C APIreturn PyModule_Create(&matrix_module);
}
2. 编译C扩展

确保已经安装了NumPy以及Python的开发包,然后使用如下命令编译C扩展:

gcc -shared -o matrix_extension.so -I/usr/include/python3.x -lpython3.x matrix_multiply.c -lpython3.x -lm

请根据你的Python版本和路径调整上述命令。

3. 在Python中使用C扩展

接下来,在Python脚本中导入并使用这个C扩展来加速矩阵乘法运算。

import numpy as np
import matrix_extension# 创建两个随机矩阵
n = 1000
A = np.random.rand(n, n)
B = np.random.rand(n, n)# 使用C扩展进行矩阵乘法
C = matrix_extension.matrix_multiply(A, B, n)print("Resulting matrix shape:", C.shape)

通过这种方式,我们利用C语言的直接内存访问和控制能力,绕过了Python解释器的层次,实现了高效的矩阵乘法运算,显著提高了执行速度。

😍😍 大量H5小游戏、微信小游戏、抖音小游戏源码😍😍
😍😍试玩地址: https://www.bojiogame.sg😍😍
😍看上哪一款,需要源码的csdn私信我😍

————————————————

​最后我们放松一下眼睛
在这里插入图片描述

相关文章:

Python中使用C扩展详解

文章目录 1. Python/C API示例2. Cython示例3. ctypes关于C扩展的进一步讨论安全性和兼容性性能优化策略调试C扩展发布和分发C扩展 应用实例&#xff1a;加速矩阵乘法运算1. 准备C扩展代码2. 编译C扩展3. 在Python中使用C扩展 在Python中&#xff0c;使用C扩展是一种提高程序性…...

llama使用tutorial微调(windows版本)

Llama3-Tutorial/docs/assistant.md at main SmartFlowAI/Llama3-Tutorial GitHub 有一些命令需要修改 前期的安装还是要按照教程搞的 streamlit run ~/Llama3-Tutorial/tools/internstudio_web_demo.py \ ~/model/Meta-Llama-3-8B-Instruct 改为了 streamlit run .\Ll…...

MyBatis操作数据库(动态SQL)

1 动态SQL 动态SQL是MyBatis的特征之一&#xff0c;能够完成不同条件下不同的SQL拼接 1.1 <if>标签 在注册用户的时候&#xff0c;可能会有这样一个问题&#xff0c;由于注册分为两种字段&#xff1a;必填字段和非必填字段&#xff0c;如果在添加用户的时候有不确定的…...

python发票真伪查验开发文档、票据OCR、数电票查验

想象一下&#xff0c;只需一行行简洁的代码&#xff0c;复杂繁琐的发票审核工作瞬间变得井然有序。翔云发票查验开发文档详尽易懂&#xff0c;即便是Python新手也能迅速上手&#xff0c;搭建起自己的发票真伪查验系统。无论是纸质发票的扫描图像&#xff0c;还是电子发票的数据…...

Unity构建详解(12)——自动构建

【前言】 自动构建是指整个构建流程不需要人工操作&#xff0c;只需要输入启动构建指令即可获取构建结果。实现这样的自动构建需要满足以下条件&#xff1a; 支持命令行参数启动 我们不可能每次构建时都打开Unity去手动点击构建&#xff0c;必须支持通过命令行启动Unity自动执…...

中文编程降低了中文环境下编程入门的门槛

近年来&#xff0c;随着编程技术的普及和中文编程环境的日益成熟&#xff0c;越来越多的开发者开始使用中文进行编程。中文编程不仅提高了代码的可读性和理解性&#xff0c;而且在一定程度上降低了中文环境下编程的入门门槛。本文将详细探讨中文编程的优势&#xff0c;以及它如…...

通过内网穿透免费部署我们的springboot+vue项目 实现跟服务器一样的效果

前文讲到通过内网穿透能够实现远程访问个人电脑的静态资源。本文将讲解通过内网穿透实现远程访问本地的项目&#xff0c;实现跟部署到服务器一样的效果&#xff1a;前文链接&#xff1a;通过内网穿透实现远程访问个人电脑资源详细过程&#xff08;免费&#xff09;&#xff08;…...

SMB攻击利用之-mimikatz上传/下载流量数据包逆向分析

SMB协议作为windows环境下最为常见的一种协议,在历史上出现过无数的通过SMB协议进行网络攻击利用的案例,包括针对SMB协议本身以及通过SMB协议实施网络攻击。 本文将介绍一种通过SMB协议的常见利用方式,即向远程主机传输mimikatz,作为我的专栏《SMB攻击流量数据包分析》中的…...

Mysql常见数据类型探索

Mysql常见数据类型探索 数值类型 MySQL 支持所有标准 SQL 数值数据类型。 这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC)&#xff0c;以及近似数值数据类型(FLOAT、REAL 和 DOUBLE PRECISION)。 关键字INT是INTEGER的同义词&#xff0c;关键字DEC是…...

2024 年第四届长三角高校数学建模竞赛赛题B题超详细解题思路+问题一二代码分享

2024年第四届长三角数学建模竞赛B题详细解题思路 赛道B&#xff1a;人工智能范式的物理化学家 长三角分享资料&#xff08;问题一代码论文思路&#xff09;链接&#xff08;18点更新&#xff09;&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1lteKvIWNZ4v-Gd7oOcg…...

干货速学!1+X电子商务数据分析:电子商务数据分析的流程

电商数据采集API接口 生活中的数据分析 日常工作和生活中处处都有数据分析的存在&#xff0c;比如消费者在购买不同商品前&#xff0c;经常会对儿“性价比”进行简单分析&#xff0c;价格表现为固定的货币数字。性能则具体体现在商品质量、客户收务等客观因素和客户对该商品的需…...

618好物推荐大赏:2024年必囤好物一网打尽,购物攻略助你抢购无忧!

在618购物狂欢节来临之际&#xff0c;我为大家精心挑选了一系列好物&#xff0c;它们不仅品质卓越&#xff0c;更能在日常生活中为我们带来无限便利与乐趣。这里的每一款产品都经过我严格筛选&#xff0c;只为给你最优质的购物体验。让我们一起在这个618&#xff0c;发现生活中…...

【MySQL】基础操作(DDL,DML,DCL,DQL)

安装教程自行搜索&#xff0c;网上有很多 用户名设置为 root密码设置为 123456可以不这样设置&#xff0c;但要记好用户名密码&#xff0c;相关的代码也要自行更改 打开命令提示符程序(winR打开输入cmd回车) 输入&#xff1a;mysql -uroot -p 回车输入密码即可进入命令行环境…...

工厂自动化升级改造(3)-Modbus与MQTT的转换

什么是MQTT,Modbus,见下面文章 工厂自动化升级改造参考(01)--设备通信协议详解及选型-CSDN博客文章浏览阅读608次,点赞9次,收藏6次。>>特点:基于标准的以太网技术,使用TCP/IP协议栈,支持高速数据传输和局域网内的设备通信。>>>特点:跨平台的通信协议,…...

InnoDB 事务处理机制

文章目录 前言1. 事务处理挑战1.1 事务机制处理的问题1.2 并发事务带来的问题 2. InnodDB 和 ACID 模型2.1 Innodb Buffer Pool2.2 Redo log2.3 Undo log2.4 应用案例 3. 隔离级别和锁机制3.1 事务隔离级别3.1.1 READ UNCOMMITTED3.1.2 READ COMMITTED3.1.3 REPEATABLE READ3.1…...

Thymeleaf

替代jsp 功能&#xff1a;服务器渲染&#xff08;就是将服务器的数据展示在网页上&#xff09; 1、MVC概念 model 模型 javaBean(User/Book/Order...) View视图 html 服务器的动态数据 Controller控制器 Servlet MVC是在表述层开发运用的一种设计理念。主张把封装数据…...

网络学习(一)|深入了解API网关:定义、功能和关键术语

文章目录 定义主要功能关键术语 定义 API 网关&#xff08;API Gateway&#xff09;是一个核心的服务架构组件&#xff0c;用于管理、路由和保护对后端服务的访问。它充当了系统内外的接口&#xff0c;负责接收来自客户端的请求&#xff0c;并将其路由到相应的后端服务&#x…...

基于yolov8+flask搭建一个web版本的网页模型预测系统

测试环境&#xff1a; anaconda3python3.8 torch1.9.0cu111 ultralytics8.2.2 首先我们将训练好的权重放在weights目录下面 并将名字改成yolov8n.pt&#xff0c;如果不想改可以在代码app.py都把路径改过来即可。然后我们打开 python app.py之后看到 我们点击选择文件支持图…...

【北京迅为】《iTOP-3588从零搭建ubuntu环境手册》-第8章 安装编译所需要的依赖包

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…...

牛客热题:合并二叉树

牛客热题&#xff1a;二叉树与双向链表> &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...