Python扩展模块的开发

        有关python C扩展开发的教程可以参考概述 — Python 3.12.3 文档。项目已经发布至python官方的pypi里了。具体详情请见AdroitFisherman · PyPI。目前该项目还处在测试阶段。尚有部分模块需要开发和测试。

项目结构

        项目结构见下图:

代码展示与说明

        以单链表(SingleLinkedList.c)为例。代码如下所示:

        SingleLinkedList.h文件

#ifndef SINGLELINKEDLIST_INCLUDED
#define SINGLELINKEDLIST_INCLUDED
typedef PyObject* ElemType;
typedef struct Node
{PyObject_HEADElemType elem;struct Node* next;
}LNode;
typedef struct {PyObject_HEADLNode* instance;
}List;
static void LNode_destroy(LNode* self)
{Py_DECREF(self->elem);Py_DECREF(self->next);Py_TYPE(self)->tp_free(self);
}
static void List_destroy(List* self)
{Py_DECREF(self->instance);Py_TYPE(self)->tp_free(self);
}
static PyObject* LNode_new(PyTypeObject* type,PyObject* args)
{LNode* self;self = (LNode*)type->tp_alloc(type,0);if (self==NULL){PyErr_SetString(PyExc_Exception, "list node object created failure!");return NULL;}else{self->elem = NULL;self->next = NULL;return (PyObject*)self;}
}
static PyObject* List_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
{List* self;self = (List*)type->tp_alloc(type, 0);if (self==NULL){PyErr_SetString(PyExc_Exception, "list object created failure!");return NULL;}else{self->instance = NULL;return (PyObject*)self;}
}
static int LNode_init(LNode* self,PyObject*args,PyObject*kwds)
{Py_INCREF(self);return 0;
}
static int List_init(List*self,PyObject*args,PyObject*kwds)
{Py_INCREF(self);return 0;
}
static PyMemberDef LNode_members[] = {{"elem",T_OBJECT,offsetof(LNode,elem),0,""},{"next",T_OBJECT,offsetof(LNode,next),0,""},{NULL}
};
static PyMemberDef List_members[] = {{"instance",T_OBJECT,offsetof(List,instance),0,""},{NULL}
};
static PyObject* InitList(List* self, PyObject* args, PyObject* kwds)
{self->instance = (LNode*)PyMem_MALLOC(sizeof(LNode));if (self->instance==NULL){Py_RETURN_FALSE;}else{self->instance->elem = NULL;self->instance->next = NULL;Py_RETURN_TRUE;}
}
static PyObject* DestroyList(List*self,PyObject*args)
{LNode* temp = self->instance;while (self->instance!=NULL){temp = self->instance;self->instance = temp->next;PyMem_FREE(temp);temp = NULL;}Py_RETURN_TRUE;
}
static PyObject* ClearList(List*self,PyObject*args)
{LNode* temp = self->instance;while (self->instance->next!=NULL){temp = self->instance->next;self->instance->next = temp->next;PyMem_FREE(temp);temp = NULL;}Py_RETURN_TRUE;
}
static PyObject* ListEmpty(List*self,PyObject*args)
{LNode* temp = self->instance;if (temp->next!=NULL){Py_RETURN_FALSE;}else{Py_RETURN_TRUE;}
}
static PyObject* ListLength(List*self,PyObject*args)
{LNode* temp = self->instance;int counter=0;while (temp->next!=NULL){counter++;temp = temp->next;}PyObject* result = Py_BuildValue("i",counter);Py_INCREF(result);return result;
}
static PyObject* GetElem(List*self,PyObject*args)
{int index;PyObject* result;if (PyArg_ParseTuple(args,"i",&index)<0){PyErr_SetString(PyExc_Exception, "Args parsed failure!");Py_RETURN_NONE;}else {if (index<0||index>=ListLength(self,NULL)){Py_RETURN_NONE;}else{LNode* temp = self->instance->next;int counter = 0;while (counter<index){temp = temp->next;counter++;}result = temp->elem;Py_XINCREF(result);return result;}}
}
static PyObject* AddFirst(List*self,PyObject*args)
{PyObject* elem;if (PyArg_ParseTuple(args,"O",&elem)<0){Py_RETURN_FALSE;}LNode* summon = (LNode*)PyMem_MALLOC(sizeof(LNode));if (summon==NULL){Py_RETURN_FALSE;}else{Py_XINCREF(elem);summon->elem = elem;summon->next = self->instance->next;self->instance->next = summon;Py_RETURN_TRUE;}
}
static PyObject* AddAfter(List*self,PyObject*args)
{PyObject* elem;if (PyArg_ParseTuple(args, "O", &elem) < 0){Py_RETURN_FALSE;}LNode* summon = (LNode*)PyMem_MALLOC(sizeof(LNode));if (summon == NULL){Py_RETURN_FALSE;}else{LNode* temp = self->instance;while (temp->next!=NULL){temp = temp->next;}Py_XINCREF(elem);summon->elem = elem;summon->next = temp->next;temp->next = summon;Py_RETURN_TRUE;}
}
static PyObject* ListInsert(List*self,PyObject*args)
{int index;PyObject* elem;if (PyArg_ParseTuple(args, "iO", &index, &elem) < 0){PyErr_SetString(PyExc_Exception, "Args parsed failure!");Py_RETURN_FALSE;}else{if (index<0||index>ListLength(self,NULL)){Py_RETURN_FALSE;}else {LNode* temp = self->instance;LNode* summon = (LNode*)PyMem_MALLOC(sizeof(LNode));if (summon==NULL){Py_RETURN_FALSE;}else{int counter = 0;while (counter<index){temp = temp->next;counter++;}Py_XINCREF(elem);summon->elem = elem;summon->next = temp->next;temp->next = summon;Py_RETURN_TRUE;}}}
}
static PyObject* ListDelete(List*self,PyObject*args)
{int index;if (PyArg_ParseTuple(args, "i", &index) < 0){PyErr_SetString(PyExc_Exception, "Args parsed failure!");Py_RETURN_FALSE;}else{if (index<0||index>=ListLength(self,NULL)){Py_RETURN_FALSE;}else{LNode* temp = self->instance;LNode* del;int counter = 0;while (counter<index){temp = temp->next;counter++;}del = temp->next;temp->next = del->next;PyMem_FREE(del);del = NULL;Py_RETURN_TRUE;}}
}
static PyMethodDef List_methods[] = {{"init_list",InitList,METH_VARARGS,""},{"destroy_list",DestroyList,METH_VARARGS,""},{"clear_list",ClearList,METH_VARARGS,""},{"list_empty",ListEmpty,METH_VARARGS,""},{"list_length",ListLength,METH_VARARGS,""},{"get_elem",GetElem,METH_VARARGS,""},{"add_first",AddFirst,METH_VARARGS,""},{"add_after",AddAfter,METH_VARARGS,""},{"list_insert",ListInsert,METH_VARARGS,""},{"list_delete",ListDelete,METH_VARARGS,""},{NULL}
};
static PyTypeObject LNodeObject = {PyVarObject_HEAD_INIT(NULL,0).tp_name = "SingleLinkedList.LNode",.tp_new = LNode_new,.tp_init = (initproc)LNode_init,.tp_dealloc = (destructor)LNode_destroy,.tp_basicsize = sizeof(LNode),.tp_itemsize = 0,.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,.tp_members = LNode_members
};
static PyTypeObject SingleLinkedListObject = {PyVarObject_HEAD_INIT(NULL,0).tp_name="SingleLinkedList.List",.tp_new=List_new,.tp_init=(initproc)List_init,.tp_dealloc=(destructor)List_destroy,.tp_basicsize=sizeof(List),.tp_itemsize=0,.tp_flags=Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT,.tp_members=List_members,.tp_methods=List_methods
};
#endif // SINGLELINKEDLIST_INCLUDED

        SingleLinkedList.c文件

#define PY_SIZE_T_CLEAN
#include <python.h>
#include <structmember.h>
#include "SingleLinkedList.h"
static PyModuleDef module = {PyModuleDef_HEAD_INIT,.m_name="SingleLinkedList",.m_size = -1
};
PyMODINIT_FUNC PyInit_SingleLinkedList()
{PyObject* m;if (PyType_Ready(&LNodeObject)<0){return NULL;}if (PyType_Ready(&SingleLinkedListObject)<0){return NULL;}m = PyModule_Create(&module);if (m==NULL){return NULL;}Py_INCREF(&LNodeObject);if (PyModule_AddObject(m,"LNode",(PyObject*)&LNodeObject)<0){PyErr_SetString(PyExc_Exception, "list object added failure!");Py_DECREF(&LNodeObject);Py_DECREF(m);return NULL;}Py_INCREF(&SingleLinkedListObject);if (PyModule_AddObject(m,"List",(PyObject*)&SingleLinkedListObject)<0){PyErr_SetString(PyExc_Exception, "list object added failure!");Py_DECREF(&SingleLinkedListObject);Py_DECREF(m);return NULL;}return m;
}

代码封装

        SingleLinkedList.py

from AdroitFisherman.SingleLinkedList import Listclass ListObject:def __init__(self):self.__list = List()self.__list.init_list()def destroy(self):self.__list.destroy_list()def clear_list(self):self.__list.clear_list()def list_empty(self):return self.__list.list_empty()def list_length(self):return self.__list.list_length()def get_elem(self, index):return self.__list.get_elem(index)def add_first(self, elem):return self.__list.add_first(elem)def add_after(self, elem):return self.__list.add_after(elem)def list_insert(self, index, elem):return self.__list.list_insert(index, elem)def list_delete(self, index):return self.__list.list_delete(index)def __del__(self):self.__list.destroy_list()

功能描述

        该单链表实现了python的数据类型扩展。能够支持不同的python类和数据类型如int、str等的数据存储与处理。由于该项目使用到的C语言语法标准为C99。所以在使用PyTypeObject结构体进行python类信息插槽定义时可以使用结构体变量的特定初始化。同理也可使用结构体的特定初始化对PyModuleDef定义的模板进行定义与声明。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/7632.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++语法|bind1st和bind2nd的用法

文章目录 What什么是&#xff1f;How什么时候用&#xff1f;如何用&#xff1f;bind1st和bind2nd的底层实现原理my_find_if分析myBind1st分析 What什么是&#xff1f; bind1st 和bind2nd分别是一个用来绑定函数对象的第一个参数或第二个参数的适配器。它在 C98 和 C03 标准中很…

5.7代码

1.环境治理 分析&#xff1a;最开始进入了一个误区&#xff0c;觉得都有通路了直接算通路就可以&#xff0c;后来才发现居然是最小路径的总和&#xff0c;所以大概是每减一次都要算一次各点之间的最小路径了&#xff0c;然后是循环&#xff0c;到需要的条件为止 总的来说思路不…

昂科烧录器支持Infineon英飞凌的三相电机驱动器TLE9877QXA40

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Infineon英飞凌的三相电机驱动器TLE9877QXA40已经被昂科的通用烧录平台AP8000所支持。 TLE9877QXA40是一款单芯片三相电机驱动器&#xff0c;集成了行业标准的ARMCortex™M3 内…

【前端】实现表格简单操作

简言 表格合并基础篇 本篇是在上一章的基础上实现&#xff0c;实现了的功能有添加行、删除行、逆向选区、取消合并功能。 功能实现 添加行 添加行分为在上面添加和在下面追加行。 利用 insertAdjacentElement 方法实现&#xff0c;该方法可以实现从前插入元素和从后插入元…

MySQL学习笔记9——触发器和权限管理

触发器和权限管理 一、触发器1、如何操作触发器2、触发器的优缺点 二、权限管理1、角色的作用2、角色的操作3、用户的操作 一、触发器 当商品信息和库存信息分别存放在两个不同的数据表中时&#xff0c;可以创建一个触发器&#xff0c; 让商品信息数据的插入操作自动触发库存数…

游戏中常用的设计模式及场景

常用的游戏设计模式及其场景有&#xff1a; 状态模式&#xff08;State Pattern&#xff09;&#xff1a;该模式定义了一系列状态和状态之间的转移关系&#xff0c;可以用于控制游戏中各个元素的行为。例如&#xff0c;在一款格斗游戏中&#xff0c;玩家的角色可以处于站立、跑…

安卓通信方式简介

目录 一、Binder二、Socket三、Binder与Socket四、Handler 一、Binder Binder作为Android系统提供的一种IPC机制&#xff0c;无论从系统开发还是应用开发&#xff0c;都是Android系统中最重要的组成。 二、Socket Socket通信方式也是C/S架构&#xff0c;比Binder简单很多。在…

Llama3-Tutorial之Llama3 Agent能力体验+微调(Lagent版)

Llama3-Tutorial之Llama3 Agent能力体验微调&#xff08;Lagent版&#xff09; 参考&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 1. 微调过程 使用XTuner在Agent-FLAN数据集上微调Llama3-8B-Instruct&#xff0c;以让 Llama3-8B-Instruct 模型获得智能体能力…

期权怎么开户?

今天期权懂带你了解期权怎么开户&#xff1f;近年来&#xff0c;随着股市的持续低迷&#xff0c;市场交易痛点越发明显的氛围中&#xff0c;所以有人看到了双向交易的期权。 期权怎么开户&#xff1f; 1、首先是证券账户内的资金需要满足50万保留20个交易日&#xff1b; 2、其…

elementUI table表格相同元素合并行----支持多列

效果图如下: vue2代码如下&#xff1a; 只粘贴了js方法哦&#xff0c; methods: {// 设置合并行 setrowspans() { const columns [‘name’, ‘value’]; // 需要合并的列名 // 为每个需要合并的列设置默认 rowspan this.tableData.forEach(row > { columns.forEach(col …

L2网络和L3网络(L2VPN和L3VPN)

L2网络和L3网络是计算机网络体系结构中按照OSI模型或TCP/IP模型的层次来区分的两种不同类型的网络。 L2网络&#xff08;数据链路层网络&#xff09; L2网络指的是第二层网络&#xff0c;对应于OSI模型中的数据链路层。这一层的主要职责是处理数据帧&#xff08;frames&#…

Google Play开发者账号为什么会被封?如何解决关联账号问题?

Google Play是Google提供的一个应用商店&#xff0c;用户可以在其中下载并安装Android设备上的应用程序、电影、音乐、电子图书等。Google Play是Android平台上较大的应用市场&#xff0c;包含了数百万个应用程序和游戏。但是谷歌对于上架应用的审核越趋严格&#xff0c;开发者…

【AIGC调研系列】VILA-1.5版本的视频理解功能如何

VILA-1.5版本的视频理解功能表现出色&#xff0c;具有显著的突破。这一版本不仅增强了视频理解能力&#xff0c;还提供了四种不同规模的模型供用户选择&#xff0c;以适应不同的应用需求和计算资源限制[1][2][3]。此外&#xff0c;VILA-1.5支持在笔记本等边缘设备上部署&#x…

解决RTC内核驱动的问题bm8563

常用pcf-8563 , 国产平替BM8563(驱动管脚一致)&#xff1b; 实时时钟是很常用的一个外设&#xff0c;通过实时时钟我们就可以知道年、月、日和时间等信息。 因此在需要记录时间的场合就需要实时时钟&#xff0c;可以使用专用的实时时钟芯片来完成此功能 RTC 设备驱动是一个标准…

CSS学习笔记之基础教程(二)

上节内容CSS学习笔记之基础教程&#xff08;一&#xff09; 6、边距 6.1 外边距&#xff1a;margin 6.1.1 外边距 marginmargin-topmargin-leftmargin-bottommargin-right <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8…

Linux网络—PXE高效批量网络装机

目录 一、部署PXE远程安装服务 1、搭建PXE远程安装服务器 1&#xff09;安装并启用 TFTP 服务 2&#xff09;安装并启用 DHCP 服务 3&#xff09;准备 Linux 内核、初始化镜像文件 4&#xff09;准备 PXE 引导程序 5&#xff09;安装FTP服务&#xff0c;准备CentOS 7 安…

智慧公厕,让您告别节假日的排队烦恼!

尊敬的读者朋友们&#xff0c;您是否曾在美丽的景区中&#xff0c;因为公共厕所排队问题而感到焦虑&#xff1f;五一假期&#xff0c;一个小小的排队可能会影响您的出游心情。但是&#xff0c;别担心&#xff0c;现在有了智慧公厕&#xff0c;这个问题终于可以轻松解决了&#…

李秘书讲写作:不准确用语可能成为谣言传播主因

李秘书讲写作&#xff1a;不准确用语可能成为谣言传播主因 李秘书发现&#xff0c;一些报刊、电台和媒体上关于新闻资讯类报道中&#xff0c;有些不准确用词、用语愈演愈烈。看起来不是什么大事&#xff0c;但细究起来问题不小&#xff0c;而且可能是诱发以谣传谣、以讹传讹的…

从简单逻辑到复杂计算:感知机的进化与其在现代深度学习和人工智能中的应用(下)

文章目录 第一章&#xff1a;感知机的局限性1.1 异或门的挑战1.2 线性与非线性问题 第二章&#xff1a;多层感知机2.1 已有门电路的组合2.2 实现异或门 第三章&#xff1a;从与非门到计算机 文章文上下两节 从简单逻辑到复杂计算&#xff1a;感知机的进化与其在现代深度学习和人…

unity基础(一)

内容概要&#xff1a; 生命周期函数vector3 位置 方向 缩放旋转等信息Vector3欧拉角和Quaternion四元素unity脚本执行顺序设置 一 生命周期函数 方法说明Awake最早调用,所以一般可以再此实现单例模式OnEnable组件激活后调用,在Awake后会调用一次Start在Update之前调用一次&a…