Python扩展模块的开发

news2024/10/7 2:18:04

        有关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_HEAD
    ElemType elem;
    struct Node* next;
}LNode;
typedef struct {
    PyObject_HEAD
    LNode* 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 List


class 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.coloradmin.cn/o/1649160.html

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

相关文章

uniapp video 层级覆盖

层级覆盖 cover-view组件 我这里做了个判断 监听全屏时隐藏按钮 根据项目需求自行更改

KIE关键信息抽取——SDMG-R

https://arxiv.org/pdf/2103.14470https://arxiv.org/pdf/2103.14470 1.概述 背景:传统的关键信息提取方法依赖于模板匹配,这使它们难以泛化到未见过的模板,且对文本识别错误不够鲁棒。SDMG-R方法:提出一种端到端的双模态图推理方法,通过构建双模态图(视觉和文本特征),…

Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作

Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 前言 通过前三篇Sprin…

速看!这次主食冻干评测极可能被商家恶意举报~VE、希喂、PR真实测评

我发现还是有不少铲屎官局限于“进口最高贵”&#xff0c;盲目的迷信进口产品。看到进口粮就盲买&#xff0c;甚至过分的贬低国产品牌&#xff0c;将国产粮贴上“不靠谱”“不合格”等标签。 最近&#xff0c;我针对主食冻干的国内、国际标准&#xff0c;相关规范文件&#xf…

小红书餐饮推广怎么合作?纯干货

小红书作为国内领先的生活方式分享平台&#xff0c;其用户群体主要集中在一二线城市&#xff0c;年龄分布在18-35岁之间&#xff0c;其中女性用户占比高达80%。这部分用户具有较高的消费能力、审美追求和品质生活需求&#xff0c;对美食有着极高的兴趣和消费意愿&#xff0c;为…

数据结构---动态数组

一、数据结构基本理论 数据结构是相互之间存在一种或多种特定关系的数据元素的集合。强调数据元素之间的关系 算法五个特性&#xff1a; 输入、输出、有穷、确定、可行 数据结构分类&#xff1a; 逻辑结构&#xff1a;集合、线性结构、树形结构、图形结构 物理…

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

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

zabbix监控方式(zabbix-trapper)

中文&#xff1a;zabbix采集器&#xff0c;即zabbix sender 。 Zabbix-Trapper 监控方式可以一次批量发送数据给Zabbix Server&#xff0c;与主动模式不同&#xff0c;Zabbix-Trapper 可以让用户控制数据的发送&#xff0c;而不用Zabbix-Agent进程控制&#xff0c;这意味着可以…

数据挖掘算法原理与实践:决策树

第2关&#xff1a;决策树算法原理 任务描述 本关任务&#xff1a;根据本关所学知识&#xff0c;完成 calcInfoGain 函数。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 信息熵&#xff1b;条件熵&#xff1b;信息增益。 信息熵 信息是个很抽象的概念。…

2.4V转3.8V/3.9V供电升压方案:为水表提供稳定电力

随着科技的不断发展&#xff0c;水表等智能设备在我们的生活中扮演着越来越重要的角色。为了让水表得以正常工作&#xff0c;稳定的电力供应是至关重要的。在这篇文章中&#xff0c;我们将探讨一种2.4V转3.8V/3.9V供电方案&#xff0c;以确保为水表提供稳定的电力。 为了实现2…

算法提高之玉米田

算法提高之玉米田 核心思想&#xff1a;状态压缩dp 将图存入g数组 存的时候01交换一下方便后面判断即g数组中0为可以放的地方 state中1为放的地方 这样只要state为1 g为0就可以判断不合法 #include <iostream>#include <cstring>#include <algorithm>#includ…

访问网络附加存储:nfs

文章目录 访问网络附加存储一、网络附加存储1.1、存储类型1.3、通过NFS挂载NAS1.4、NFS挂载过程服务端客户端 二、实验&#xff1a;搭建NFS服务端及挂载到nfs客户端服务端客户端测试命令合集服务端客户端 访问网络附加存储 一、网络附加存储 1.1、存储类型 DAS&#xff1a;Di…

照片太大上传不了怎么缩小?教你几招压缩图片

在日常的工作和学习中&#xff0c;我们经常要用到一些图片文件&#xff0c;储存的图片多了之后&#xff0c;会对我们的电脑或者手机有影响&#xff0c;需要我们使用图片处理工具来压缩图片大小&#xff0c;那么有没有比较简单的图片压缩的方法呢&#xff1f;试试今天分享的几个…

c++ cpp 在类中执行线程 进行恒定计算

在编程中&#xff0c;顺序执行是常见的模式&#xff0c;但是对cpu的利用率不是很高&#xff0c;采用线程池&#xff0c;又太麻烦了&#xff0c;原因是还得不断地把任务拆分&#xff0c;扫描返回值。 如果 初始化n个类的时候&#xff0c;传递数据自身即可异步计算&#xff0c;那…

产品专访|“产品”远程运维系统与“设备”远程运维系统的区别?

在日益复杂的工业制造环境下&#xff0c;远程运维已经成为生产制造企业不可或缺的一部分。在这个大背景下&#xff0c;产品远程运维系统和设备远程运维系统的需求越来越多&#xff0c;各自发挥着独特的作用。然而&#xff0c;尽管它们都涉及到远程运维的概念&#xff0c;但在实…

好消息|5月6日起换发补发出入境证件可“全程网办”

国家移民管理局从2024年5月6日起&#xff0c;实施若干便民利企出入境管理的六项政策措施&#xff0c;包括在北京等20个城市试点实行换发补发出入境证件的“全程网办”&#xff0c;该举措对于访问学者、博士后研究人员及联合培养博士都是利好消息。故知识人网小编转载发布。 为更…

【影片欣赏】【指环王】【魔戒:护戒使者 The Lord of the Rings: The Fellowship of the Ring】

2001年发行&#xff0c;Extended DVD Edition Part One 1. Prologue: One Ring to Rule Them All… 2. Concerning Hobbits 3. The Shire 4. Very Old Friends 5. A Long-expected Party 6. Farewell Dear Bilbo 7. Keep It Secret, Keep It Safe 8. The Account of Isildur 9…

在ubuntu虚拟机中手动安装VMware Tools(VMware Workstation 17 player)

可参考官方文档&#xff1a;在 Linux 虚拟机中手动安装 VMware Tools 以下列出我在安装过程中遇见的问题&#xff1a; 1、“安装VMware Tools”选项为灰&#xff0c;无法选中 原因是VMware Tools的安装包镜像在Player的安装目录下&#xff0c;需要在虚拟机启动的时候加载这个…

el-collapse中title两端对齐

el-collapse中title两端对齐 最后效果 <el-collapse><el-collapse-item title"" name"1"><template slot"title"><div class"tablis"><div>04-02-18</div><div>XXXXXXX</div><di…