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://xiahunao.cn/news/3016030.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

我独自升级崛起一键下载 我独自升级崛起一键下载安装教程

将于5月8日向全球绽放的《我独自升级&#xff1a;崛起》&#xff0c;标志着动作角色扮演类游戏的新纪元。它深挖同名动漫与网络漫画的丰富底蕴&#xff0c;誓言以无尽的魅力引导玩家涉足一个深广莫测、波澜壮阔的奇幻领域。该游戏巧妙地植根于一个前所未有的赛博武侠天地间&…

套管外径测量仪 多尺寸型号 规格全可定制

套管&#xff08;bushing&#xff09;是一种将带电导体引入电气设备或穿过墙壁的一种绝缘装置。前者称为电器套管&#xff0c;后者称为穿墙套管。套管通常用在建筑地下室&#xff0c;是用来保护管道或者方便管道安装的铁圈。套管的分类有刚性套管、柔性防水套管、钢管套管及铁皮…

智慧公厕:数据驱动的新时代公共厕所管理

公共厕所是城市的重要基础设施&#xff0c;直接关系到人民群众的生活质量和城市形象。然而&#xff0c;长期以来&#xff0c;公共厕所的管理问题一直困扰着城市管理者。为了解决这个难题&#xff0c;智慧公厕应运而生。本文将以智慧公厕源头实力厂家广州中期科技有限公司&#…

我独自升级崛起怎么下载 我独自升级崛起下载教程来了

《我独自升级&#xff1a;崛起》作为一款炙手可热的游戏&#xff0c;其非凡的品质迅速聚拢了大量玩家的目光&#xff0c;就如同磁铁吸引铁屑一般&#xff0c;展现了优质游戏所固有的强大吸引力。在这款游戏中&#xff0c;每位玩家都能化身成为拥有超凡能力的英雄&#xff0c;体…

解析Linux键盘组合键产生信号的完整过程:从硬件中断到信号发送

前言 每一个了解Linux的都知道这样一个知识&#xff0c;CtrlC组合键能够终止一个进程。 个人了解进程相关知识之后知道&#xff0c;一个进程被终止只会有有三种情况&#xff1a; 代码运行完毕&#xff0c;结果正确代码运行完毕&#xff0c;结果不正确代码运行异常&#xff…

0508_IO2

练习&#xff1a; 将一张图片修改为德国国旗 1 #include <stdio.h>2 #include <string.h>3 #include <stdlib.h>4 #include <sys/types.h>5 #include <unistd.h>6 #include <sys/stat.h>7 #include <fcntl.h>8 #include <pthrea…

恒创科技「5月活动」中国香港/美国服务器配置及价格汇总

值此 5 月&#xff0c;各大云服务商的促销活动也是接连不断。近日&#xff0c;恒创科技上线了 5 月出海乐购“惠”活动&#xff0c;从 4 月 28 日开始&#xff0c;持续整个 5 月份。活动分精选云产品、主流物理服务器、DDoS 防护、免费试用等四大专区&#xff0c;包含几十款企业…

【强化学习】公平性Actor-Critic算法

Bringing Fairness to Actor-Critic Reinforcement Learning for Network Utility Optimization 阅读笔记 Problem FormulationLearning AlgorithmLearning with Multiplicative-Adjusted RewardsSolving Fairness Utility Optimization Evaluations 在网络优化问题中&#xff…

Windows11系统安装Mysql8之后,启动服务net start mysql报错“服务没有响应控制功能”的解决办法

问题 系统环境&#xff1a;Windows11 数据库版本&#xff1a;Mysql8 双击安装&#xff0c;一路下一步&#xff0c;完成&#xff0c;很顺利&#xff0c;但是开启服务后 net start mysql 报错&#xff1a; 服务没有响应控制功能。 请键入 NET HELPMSG 2186 以获得更多的帮助 不…

RabbitMQ是如何保证消息可靠性的?——Java全栈知识(16)

RabbitMQ 的消息不可靠也就是 RabbitMQ 消息丢失只会发生在以下几个方面&#xff1a; 生产者发送消息到 MQ 或者 Exchange 过程中丢失。Exchange 中的消息发送到 MQ 中丢失。消息在 MQ 或者 Exchange 中服务器宕机导致消息丢失。消息被消费者消费的过程中丢失。 大致就分为生…

C语言 函数的定义与调用

上文 C语言 函数概述 我们对函数进行了概述 本文 我们来说函数的定义和调用 C语言规定 使用函数之前&#xff0c;首先要对函数进行定义。 根据模块化程序设计思想&#xff0c;C语言的函数定义是互相平行、独立的&#xff0c;即函数定义不能嵌套 C语言函数定义 分为三种 有参函…

中国居民消费新特征:中枢回落,即时满足,去地产化

随着收入预期和财富效应的转变&#xff0c;居民更倾向于通过短期集中式的消费来获得即时满足的快乐&#xff0c;服务消费表现出了更强的韧性。服务消费强于商品消费、消费去地产化、汽车挑大梁的特征延续。 特征一&#xff1a;消费倾向高于2020-22年&#xff0c;低于2017-19年…

QX-mini51单片机学习(1)---电子电路基础

目录 1电平特性 2单片机io口简绍 3初识电容电阻 4初识电路原理图 5单片机最小系统结构 6单片机工作基本时序 1电平特性 单片机是一种数字集成芯片&#xff0c;数字电路中两种电平&#xff0c;高电平与低电平 高电平&#xff1a;5v 低电平&#xff1a;0v TTL电平信号…

非平衡数据处理-Tomek link算法介绍,代码和实战测评

作者Toby&#xff0c;来源公众号&#xff1a;Python风控模型&#xff0c;非平衡数据处理-Tomek link算法 概述 非平衡数据在金融风控领域、反欺诈客户识别、广告智能推荐和生物医疗中普遍存在。一般而言&#xff0c;不平衡数据正负样本的比例差异极大&#xff0c;如在Kaggle竞…

[华为OD]C卷 精准核算检测 100

题目&#xff1a; 为了达到新冠疫情精准防控的需要&#xff0c;为了避免全员核酸检测Q带来的浪费&#xff0c;需要精准圈定可 能被感染的人群。现在根据传染病流调以及大数据分析&#xff0c;得到了每个人之间在时间、空间上是 否存在轨迹的交叉现在给定一组确诊人员编号&…

多微信管理不过来?你需要一个微信神器

很多企业都在面临以下几个问题&#xff1a; 1、希望进行微信营销转型&#xff0c;但是不知道如何入手&#xff1b; 2、拥有多个微信号&#xff0c;但不想拿着多台手机&#xff0c;希望能够集中管理所有微信号&#xff1b; 3、希望使用app替代传统的营销体系&#xff0c;并确…

RS0108YQ20功能和参数介绍及高速数据传输中的优势

RS0108YQ20功能和参数介绍及高速数据传输中的优势-公司新闻-配芯易-深圳市亚泰盈科电子有限公司 RS0108YQ20是一款电平转换器&#xff0c;也称为电平移位器&#xff0c;它的主要功能是在不同的电源电压或逻辑电平之间提供双向信号转换。以下是RS0108YQ20的一些关键参数和功能特…

链表成环或多分枝问题

问题概述 这类问题主要和数论结合到一起。 这类问题主要的解决技巧就是画图&#xff0c;跟着图来写代码&#xff0c;不然代码5分钟&#xff0c;调试2小时。 因为每个节点可以指向下一个节点&#xff0c;那么两个节点就可以指向同一个节点&#xff1b;或者链表的末尾节点指向…

JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式

技术栈 1. 开发语言&#xff1a;JAVA 2. 数据库&#xff1a;MySQL 3. 后端框架&#xff1a;Spring boot 4. 前端框架&#xff1a;VUE2 5. 电子班牌&#xff1a; Android 7.1 6. 小程序&#xff1a;原生开发 7. 多学校Saas 模式 电子班牌是一款智慧校园管理工具&#xf…

自动语音识别

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…