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,一经查实,立即删除!

相关文章

5.7代码

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

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

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

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

简言 表格合并基础篇 本篇是在上一章的基础上实现&#xff0c;实现了的功能有添加行、删除行、逆向选区、取消合并功能。 功能实现 添加行 添加行分为在上面添加和在下面追加行。 利用 insertAdjacentElement 方法实现&#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 …

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

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

解决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 安…

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

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

unity基础(一)

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

软件架构的艺术:探索演化之路上的18大黄金原则

实际工作表明&#xff0c;一步到位的设计往往不切实际&#xff0c;而演化原则指导我们逐步优化架构&#xff0c;以灵活响应业务和技术的变化。这不仅降低了技术债务和重构风险&#xff0c;还确保了软件的稳定性和可扩展性。同时&#xff0c;架构的持续演进促进了团队协作&#…

java:递归实现的案例

//求第20个月兔子的对数 //每个月兔子对数&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8 public class Test {//求第20个月兔子的对数//每个月兔子对数&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8pu…

Linux进程——Linux进程与进程优先级

前言&#xff1a;在上一篇了解完一部分常见的进程状态后&#xff0c;我们先来把剩下的进程状态了解一下&#xff0c;再来进入进程优先级的学习&#xff01; 如果对前面Linux进程不太熟悉可以先阅读&#xff1a; Linux进程 本篇主要内容&#xff1a; 僵尸进程和孤儿进程 Linux进…

LLM——用于微调预训练大型语言模型(LLM)的GPU内存优化与微调

前言 GPT-4、Bloom 和 LLaMA 等大型语言模型&#xff08;LLM&#xff09;通过扩展至数十亿参数&#xff0c;实现了卓越的性能。然而&#xff0c;这些模型因其庞大的内存需求&#xff0c;在部署进行推理或微调时面临挑战。这里将探讨关于内存的优化技术&#xff0c;旨在估计并优…

LTE的EARFCN和band之间的对应关系

一、通过EARFCN查询对应band 工作中经常遇到只知道EARFCN而需要计算band的情况&#xff0c;因此查了相关协议&#xff0c;找到了他们之间的对应关系&#xff0c;可以直接查表&#xff0c;非常方便。 具体见&#xff1a; 3GPP TS 36.101 5.7.3 Carrier frequency and EAR…

单细胞|GeneTrajectory·基因轨迹

跑完了&#xff0c;记录一下&#xff0c;顺便写写我在使用中遇到的问题&#xff0c;欢迎讨论&#xff5e; 声明&#xff1a;我是用自己数据跑的&#xff0c;因为还未发表所以就还是借用官网的图啦&#xff5e; 1.准备 library(GeneTrajectory) library(Seurat) library(dply…

OpenCV 入门(五) —— 人脸识别模型训练与 Windows 下的人脸识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…