python函数定义和其四种参数_『Python CoolBook』C扩展库_其四_结构体操作与Capsule...

本文介绍了如何在Python C扩展库中处理C语言的结构体,特别是将结构体转换为胶囊(Capsule)对象,并探讨了内存管理和垃圾回收。通过`PyCapsule_New()`创建胶囊,使用`PyCapsule_GetPointer()`解析胶囊回结构体。文章还展示了如何在Python中创建和使用结构体,以及进行相关运算。
摘要由CSDN通过智能技术生成

一、Python生成C语言结构体

C语言中的结构体传给Python时会被封装为胶囊(Capsule),

我们想要一个如下结构体进行运算,则需要Python传入x、y两个浮点数,

typedef struct Point {

double x,y;

} Point;

然后对这两个浮点数解析后生成C中Point的结构体,如下,

/* Create a new Point object */

static PyObject *py_Point(PyObject *self, PyObject *args) {

Point *p;

double x,y;

if (!PyArg_ParseTuple(args,"dd",&x,&y)) {

return NULL;

}

p = (Point *) malloc(sizeof(Point));

p->x = x;

p->y = y;

return PyPoint_FromPoint(p, 1);

}

上面最后一句将使用C中的结构体构建Python胶囊对象并返回给Python,

/* Destructor function for points */

static void del_Point(PyObject *obj) {

free(PyCapsule_GetPointer(obj,"Point"));

}

static PyObject *PyPoint_FromPoint(Point *p, int must_free) {

/* 胶囊和C指针类似。在内部,它们获取一个通用指针和一个名称,可以使用

PyCapsule_New() 函数很容易的被创建。 另外,一个可选的析构函数能被

绑定到胶囊上,用来在胶囊对象被垃圾回收时释放底层的内存*/

return PyCapsule_New(p, "Point", must_free ? del_Point : NULL);

}

PyCapsule_New():从结构体创建胶囊

PyCapsule_GetPointer():提取胶囊中的指针,使用 PyCapsule_GetPointer() 函数并指定名称。 如果提供的名称和胶囊不匹配或其他错误出现,那么就会抛出异常并返回NULL。实际上就是从胶囊转换回结构体

效果如下,

>>> import sample

>>> p1 = sample.Point(2,3)

>>> p2 = sample.Point(4,5)

>>> p1

>>> p2

总结

本节中,一对工具函数—— PyPoint_FromPoint() 和 PyPoint_AsPoint() 被用来创建和从胶囊对象中提取Point实例。 在任何扩展函数中,我们会使用这些函数而不是直接使用胶囊对象。 这种设计使得我们可以很容易的应对将来对Point底下的包装的更改。 例如,如果你决定使用另外一个胶囊了,那么只需要更改这两个函数即可。

对于胶囊对象一个难点在于垃圾回收和内存管理。 PyPoint_FromPoint() 函数接受一个 must_free 参数, 用来指定当胶囊被销毁时底层Point * 结构体是否应该被回收。 在某些C代码中,归属问题通常很难被处理(比如一个Point结构体被嵌入到一个被单独管理的大结构体中)。 程序员可以使用 extra 参数来控制,而不是单方面的决定垃圾回收。 要注意的是和现有胶囊有关的析构器能使用 PyCapsule_SetDestructor() 函数来更改。

二、Python中的C结构体传入C语言进行运算

/* Utility functions */

static Point *PyPoint_AsPoint(PyObject *obj) {

return (Point *) PyCapsule_GetPointer(obj, "Point");

}

static PyObject *py_distance(PyObject *self, PyObject *args) {

Point *p1, *p2;

PyObject *py_p1, *py_p2;

double result;

if (!PyArg_ParseTuple(args,"OO",&py_p1, &py_p2)) {

return NULL;

}

if (!(p1 = PyPoint_AsPoint(py_p1))) {

return NULL;

}

if (!(p2 = PyPoint_AsPoint(py_p2))) {

return NULL;

}

result = distance(p1,p2);

return Py_BuildValue("d", result);

}

将两个结构体转为C指针存储后,分别使用PyCapsule_GetPointer()提取指针信息转换为结构体,计算后返回。

>>> sample.distance(p1,p2)

2.8284271247461903

『Python CoolBook』C扩展库_其五_C语言层面Python库之间调用API

点击进入项目 一.C层面模块添加API 我们仍然操作如下结构体, #include typedef struct Point { double x,y; } Point; ...

『Python CoolBook』C扩展库_其一_用法讲解

不依靠其他工具,直接使用Python的扩展API来编写一些简单的C扩展模块. 本篇参考PythonCookbook第15节和Python核心编程完成,值得注意的是,Python2.X和Python3. ...

『Python CoolBook』C扩展库_其三_简单数组操作

点击进入项目 这里的数组要点在于: 数组结构,array.array或者numpy.array 本篇的数组仅限一维,不过基础的C数组也是一维 一.分块讲解 源函数 /* Average values ...

『Python CoolBook』C扩展库_其六_线程

GIL操作 想让C扩展代码和Python解释器中的其他进程一起正确的执行, 那么你就需要去释放并重新获取全局解释器锁(GIL). 在Python接口封装中去释放并重新获取全局解释器锁(GIL),此时本 ...

『Python CoolBook』C扩展库_其二_demo演示

点击进入项目 C函数源文件 /* sample.c */ #include "sample.h" /* Compute the greatest common divisor */ ...

『Python CoolBook』C扩展库_其六_从C语言中调用Python代码

点击进入项目 一.C语言运行pyfun的PyObject对象 思路是在C语言中提供实参,传给python函数: 获取py函数对象(PyObject),函数参数(C类型) 获取GIL(PyGILStat ...

『Python CoolBook』使用ctypes访问C代码_下_demo进阶

点击进入项目 这一次我们尝试一下略微复杂的c程序. 一.C程序 头文件: #ifndef __SAMPLE_H__ #define __SAMPLE_H__ #include

『Python CoolBook』使用ctypes访问C代码_上_用法讲解

一.动态库文件生成 源文件hello.c #include "hello.h" #include void hello(const char *na ...

『Python CoolBook』Cython

github地址 使用Cython导入库的话,需要一下几个文件: .c:C函数源码 .h:C函数头 .pxd:Cython函数头 .pyx:包装函数 setup.py:python 本节示例.c和.h ...

随机推荐

SharePoint 2013 通过JavaScript实现列表标题列宽度可拖动

前言 最近有个新需求,用户希望标题栏可以拖动宽度,其实觉得没什么用,既然用户要了又推不掉,就勉为其难实现一下吧. 其实原理比较简单,就是利用JavaScript对标题栏进行宽度控制,然后从网上搜了一下 ...

liunx常用的命令

计算机网络的主要优点是能够实现资源和信息的共享,并且用户可以远程访问信息.Linux提供了一组强有力的网络命令来为用户服务,这些工具能够帮助用户登录到远程计算机上.传输文件和执行远程命令等. 本章介绍 ...

Spark大数据的学习历程

Spark主要的编程语言是Scala,选择Scala是因为它的简洁性(Scala可以很方便在交互式下使用)和性能(JVM上的静态强类型语言).Spark支持Java编程,但对于使用Java就没有了Sp ...

20145236 《Java程序设计》实验一实验报告

北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1452 指导教师:娄嘉鹏 实验日期:2016.04.08 实验名称:Java开发环境的熟悉(Linux + Eclipse) 实 ...

FFmpeg在Android上的移植之第一步

http://blog.sina.com.cn/s/blog_69a04cf40100x1fr.html 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的. ...

对原生态jdbc程序中问题总结

import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...

L012-oldboy-mysql-dba-lesson12

L012-oldboy-mysql-dba-lesson12 graphite监控mysql可以达到秒级别 Zabbix for mysql NagiosXI daemontools linux    ...

数据库文档生成工具——word2chm,SqlSpec

首先使用代码生成器可以生成word版本的数据库文档. 转成chm格式的更加小巧和方便~ SqlSpec是个好工具,可以生成所有数据库相关的信息 之后可以一键生成chm文档.

android学习之-Theme和Style

android学习之-Theme和Style 分类: android 2013-10-11 15:01 960人阅读 评论(0) 收藏 举报 android style和theme的使用. style ...

在C#中初遇Socket - 1

后期项目实战:多人在线聊天室 源码位置:https://git.oschina.net/z13qu/BlogProjects 课前须知 这里不讲解Socket和TCP/IP的底层知识 对于初学者来说底 ...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值