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_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定义的模板进行定义与声明。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【go项目01_学习记录04】

学习记录 1 集成 Gorilla Mux1.1 为什么不选择 HttpRouter&#xff1f;1.2 安装 gorilla/mux1.3 使用 gorilla/mux1.4 迁移到 Gorilla Mux1.4.1 新增 homeHandler1.4.2 指定 Methods () 来区分请求方法1.4.3 请求路径参数和正则匹配1.4.4 命名路由与链接生成 1 集成 Gorilla Mu…

【Linux网络】PXE批量网络装机

目录 一、系统装机 1.1 三种引导方式 1.2 系统安装过程 1.3 四大重要文件 二、PXE 2.1 PXE实现原理 2.2 PXE手动搭建过程 2.3 kickstart配合pxe完成批量自动安装 一、系统装机 1.1 三种引导方式 硬盘光驱(U盘)网络启动 1.2 系统安装过程 加载boot loader加载启动安…

借势母亲节h5小游戏的作用是什么

企业商家往往喜欢借势节日开展营销&#xff0c;母亲节作为5月的重要节日自然不可错过&#xff0c;不同行业商家都有自己开展互动想要实现的效果&#xff0c;如品牌宣传曝光、引流及渠道跳转等。 基于微信社交属性&#xff0c;有利于品牌发展&#xff0c;在【雨科】平台拥有多款…

SparkSQL优化

SparkSQL优化 优化说明 缓存数据到内存 Spark SQL可以通过调用spark.sqlContext.cacheTable("tableName") 或者dataFrame.cache()&#xff0c;将表用一种柱状格式&#xff08; an inmemory columnar format&#xff09;缓存至内存中。然后Spark SQL在执行查询任务…

有什么方便实用的成人口语外教软件?6个软件教你快速进行口语练习

有什么方便实用的成人口语外教软件&#xff1f;6个软件教你快速进行口语练习 口语能力在语言学习中占据着重要的位置&#xff0c;因为它直接关系到我们与他人进行交流和沟通的效果。为了提高口语能力&#xff0c;很多成人选择通过外教软件进行口语练习&#xff0c;这些软件提供…

【强训笔记】day13

NO.1 代码实现&#xff1a; #include <iostream>#include<string>using namespace std;int n,k,t; string s;int func() {int ret0;for(int i0;i<n;i){char chs[i];if(chL) ret-1;else{if(i-1>0&&i-2>0&&s[i-1]W&&s[i-2]W) retk…

基于Springboot 的 Excel表格的导入导出

首先 &#xff0c;引入相关依赖EasyPOI <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.4.0</version></dependency> 编写实体类&#xff1a; Data AllArgs…

Java 框架安全:Struts2 漏洞序列测试.

什么是 Struts2 框架 Struts 2 是一个用于创建企业级 Java 应用程序的开源框架。它是一个 MVC&#xff08;模型-视图-控制器&#xff09;框架&#xff0c;用于开发基于 Java EE&#xff08;Java Platform, Enterprise Edition&#xff09;的 Web 应用程序。Struts 2 主要解决…

ROS机器人实用技术与常见问题解决

问题速查手册&#xff08;时实更新&#xff09;更加全面丰富的问题手册记录 1.机器人使用GPARTED挂载未分配空间 需要在图型界面下操作&#xff0c;建议使用no machine连接 安装gparted磁盘分区工具, sudo apt-get install gparted -y 启动软件 sudo gparted 点击磁盘/内存…

C# OpenCvSharp 图片找茬

C# OpenCvSharp 图片找茬 目录 效果 项目 代码 下载 效果 项目 代码 using OpenCvSharp; using System; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; namespace OpenCvSharp_Demo { public partial class Form1 : Form { …

1688快速获取整店铺列表 采集接口php Python

在电子商务的浪潮中&#xff0c;1688平台作为中国领先的批发交易平台&#xff0c;为广大商家提供了一个展示和销售商品的广阔舞台&#xff1b;然而&#xff0c;要在众多店铺中脱颖而出&#xff0c;快速获取商品列表并进行有效营销是关键。 竞争对手分析 价格比较&#xff1a;…

mysql5.7数据库安装及性能测试

mysql5.7数据库安装及性能测试 记录Centos7.9下安装mysql 5.7并利用benchmark工具简单测试mysql的性能。 测试机&#xff1a;centos7.9 配置&#xff1a;4C8G40G 1. 下安装mysql5.7 安装mysql5.7&#xff1a; # 通过官方镜像源安装$ wget http://dev.mysql.com/get/mysql57-com…

pandas索引

pandas索引 一、索引1.1 建立索引1.2 重置索引1.3 索引类型1.4 索引的属性1.5 索引的操作 一、索引 1.1 建立索引 建立索引可以在数据读取加载中指定索引&#xff1a; import pandas as pd df pd.read_excel(team.xlsx, index_colname) # 将name列设置为索引 df.head()效…

C语言 函数的定义与调用

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

Kansformer?变形金刚来自过去的新敌人

​1.前言 多层感知器(MLPs),也被称为全连接前馈神经网络,是当今深度学习模型的基础组成部分。 MLPs在机器学习中扮演着至关重要的角色,因为它们是用于近似非线性函数的默认模型,这得益于通用近似定理所保证的表达能力。然而,MLPs真的是我们能构建的最佳非线性回归器吗?尽管ML…

鸿蒙OpenHarmony南向:【Hi3516标准系统入门(命令行方式)】

Hi3516标准系统入门&#xff08;命令行方式&#xff09; 注意&#xff1a; 从3.2版本起&#xff0c;标准系统不再针对Hi3516DV300进行适配验证&#xff0c;建议您使用RK3568进行标准系统的设备开发。 如您仍然需要使用Hi3516DV300进行标准系统相关开发操作&#xff0c;则可能会…

人工智能编程的创新探索 卧龙与凤雏的畅想

在一间宽敞明亮的办公室内&#xff0c;阳光透过窗户洒在地上&#xff0c;形成一片片光斑。卧龙和凤雏正坐在舒适的办公椅上休息&#xff0c;享受着这片刻的宁静。 卧龙微微皱眉&#xff0c;一只手托着下巴&#xff0c;略显苦恼地说道&#xff1a;“现在的人工智能&#xff0c;也…

vue2人力资源项目5组织架构的增删改查

编辑表单回显 父组件&#xff1a;这里用到了父亲调子组件的方法和同步异步先后方法的处理 //methods里else if (type edit) {this.showDialog true// 显示弹层this.currentNodeId id// 记录id&#xff0c;要用它获取数据// 在子组件中获取数据// 父组件调用子组件的方法来获…

【力扣】203、环形链表 II

142. 环形链表 II 要解决这道题&#xff0c;首先需要对问题进行拆解&#xff1a; 确定链表是否存在环确定环的入口点 如何判断是否存在环呢&#xff1f;这个比较容易想到&#xff0c;使用快慢指针即可判断链表是否存在环。我们定义两个指针&#xff1a; ListNode slow head…

Redis学习4——Redis应用之限流

引言 Redis作为一个内存数据库其读写速度非常快&#xff0c;并且支持原子操作&#xff0c;这使得它非常适合处理频繁的请求&#xff0c;一般情况下&#xff0c;我们会使用Redis作为缓存数据库&#xff0c;但处理做缓存数据库之外&#xff0c;Redis的应用还十分广泛&#xff0c…