点击进入项目

一、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
<capsule object "Point" at 0x1004ea330>
>>> p2
<capsule object "Point" at 0x1005d1db0>

总结

本节中,一对工具函数—— 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扩展库_其四_结构体操作与Capsule的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. 『Python CoolBook』Cython

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

随机推荐

  1. LeetCode 237 Delete Node in a Linked List 解题报告

    题目要求 Write a function to delete a node (except the tail) in a singly linked list, given only access ...

  2. Linux命令:在线练习地址

    1.https://www.tutorialspoint.com/unix_terminal_online.php 2.https://www.tutorialspoint.com/index.htm ...

  3. AppUtil

    import java.io.File;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List; ...

  4. 【JVM】-NO.110.JVM.1 -【GC垃圾收集器】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  5. 【UML】NO.54.EBook.6.UML.2.002-【Thinking In UML 大象 第二版】- UML 核心元素

    1.0.0 Summary Tittle:[UML]NO.54.EBook.6.UML.2.002-[Thinking In UML 大象 第二版]- UML 核心元素 Style:DesignPat ...

  6. 深入理解Java虚拟机1-chap1-2-斗之气8段

    1.HotSpot VM:热点代码探测能力,与JIT技术共同进行编译优化,输出高质量代码 2.运行时数据区域 程序计数器:控制程序执行顺序,无OOM Java虚拟机栈:生命周期与线程一致,描述Java ...

  7. C++ Windows API 读写INI文件

    BOOL WritePrivateProfileString( LPCTSTR lpAppName, // INI文件中的一个字段名[节名]可以有很多个节名 LPCTSTR lpKeyName, // ...

  8. #WEB安全基础 : HTTP协议 | 0x1 TCP/IP通信

    TCP/IP是如何通信的呢? 请看图 用TCP/IP协议族通信时,会通过分层顺序与对方进行通信.发送端从应用层往下走,接受层从链路层往上走. 客户端为了浏览界面在应用层发送请求,为了方便传输在传输层的 ...

  9. 细说flask数据库迁移

    什么情况下要用数据库迁移? 在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库.最直接的方式就是删除旧表,但这样会丢失数据. 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化 ...

  10. cookie session 讲解

    cookie: cookie的定义: cookie 是由web服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息,并且在每次请求时会携带保存的数据去访问服务器,所以cookie有 ...