热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在Cython中的新式缓冲区对象中包装C指针和长度?

如何解决《如何在Cython中的新式缓冲区对象中包装C指针和长度?》经验,为你挑选了1个好方法。

我在Cython中编写了一个Python 2.7扩展模块. 如何创建一个实现新式缓冲区接口的Python对象,该接口包含C库提供给我的大块内存? 内存块只是一串字节,而不是结构或多维数组.我给了一个const void *指针和一个长度,以及一些指针保持有效的细节.

我无法复制内存 - 这会破坏我的应用程序的性能.

使用我可以简单使用的旧式缓冲区对象PyBuffer_FromMemory(),但我似乎无法找到一种类似的简单方法来生成新式缓冲区对象.

我是否必须创建自己的实现缓冲区接口的类?或者Cython提供了一种简单的方法吗?

我已经阅读了Cython文档中的Unicode和Passing Strings和Typed Memoryviews页面,但文档不精确且不够完整,并且没有类似于我想要做的示例.

这是我尝试过的(test.pyx):

from libc.stdlib cimport malloc
from libc.string cimport memcpy

## pretend that this function is in some C library and that it does
## something interesting.  (this function is unrelated to the problem
## I'm experiencing -- this is just an example function that returns a
## chunk of memory that I want to wrap in an object that follows the
## new buffer protocol.)
cdef void dummy_function(const void **p, size_t *l):
    cdef void *tmp = malloc(17)
    memcpy(tmp, "some test\0 bytes", 17)
    p[0] = tmp
    l[0] = 17

cpdef getbuf():
    cdef const void *cstr
    cdef size_t l
    dummy_function(&cstr, &l)

    ## error: test.pyx:21:20: Invalid base type for memoryview slice: void
    #cdef const void[:] ret = cstr[:l]

    ## error: test.pyx:24:9: Assignment to const 'ret'
    #cdef const char[:] ret = cstr[:l]

    ## error: test.pyx:27:27: Cannot convert 'void const *' to memoryviewslice
    #cdef char[:] ret = cstr[:l]

    ## this next attempt cythonizes, but raises an exception:
    ## $ python -c 'import test; test.getbuf()'
    ## Traceback (most recent call last):
    ##   File "", line 1, in 
    ##   File "test.pyx", line 15, in test.getbuf (test.c:1411)
    ##   File "test.pyx", line 38, in test.getbuf (test.c:1350)
    ##   File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6763)
    ##   File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3309)
    ## BufferError: Object is not writable.
    cdef char[:] ret = (cstr)[:l]

    ## this raises the same exception as above
    #cdef char[:] ret = (cstr)[:l]

    return ret

Richard Hans.. 5

您可以通过定义和特殊方法来定义实现缓冲区协议的扩展类型.例如:__getbuffer____releasebuffer__

from cpython.buffer cimport PyBuffer_FillInfo
from libc.stdlib cimport free, malloc
from libc.string cimport memcpy

cdef void dummy_function(const void **p, size_t *l):
    cdef void *tmp = malloc(17)
    memcpy(tmp, "some test\0 bytes", 17)
    p[0] = tmp
    l[0] = 17

cdef void free_dummy_data(const void *p, size_t l, void *arg):
    free(p)

cpdef getbuf():
    cdef const void *p
    cdef size_t l
    dummy_function(&p, &l)
    return MemBuf_init(p, l, &free_dummy_data, NULL)

ctypedef void dealloc_callback(const void *p, size_t l, void *arg)

cdef class MemBuf:
    cdef const void *p
    cdef size_t l
    cdef dealloc_callback *dealloc_cb_p
    cdef void *dealloc_cb_arg

    def __getbuffer__(self, Py_buffer *view, int flags):
        PyBuffer_FillInfo(view, self, self.p, self.l, 1, flags)
    def __releasebuffer__(self, Py_buffer *view):
        pass

    def __dealloc__(self):
        if self.dealloc_cb_p != NULL:
            self.dealloc_cb_p(self.p, self.l, self.dealloc_cb_arg)

# Call this instead of constructing a MemBuf directly.  The __cinit__
# and __init__ methods can only take Python objects, so the real
# constructor is here.  See:
# https://mail.python.org/pipermail/cython-devel/2012-June/002734.html
cdef MemBuf MemBuf_init(const void *p, size_t l,
                        dealloc_callback *dealloc_cb_p,
                        void *dealloc_cb_arg):
    cdef MemBuf ret = MemBuf()
    ret.p = p
    ret.l = l
    ret.dealloc_cb_p = dealloc_cb_p
    ret.dealloc_cb_arg = dealloc_cb_arg
    return ret

使用上面的(命名test.pyx),您将获得以下行为:

$ python -c 'import test; print repr(memoryview(test.getbuf()).tobytes())'
'some test\x00 bytes\x00'

我不知道是否有更简单的方法.



1> Richard Hans..:

您可以通过定义和特殊方法来定义实现缓冲区协议的扩展类型.例如:__getbuffer____releasebuffer__

from cpython.buffer cimport PyBuffer_FillInfo
from libc.stdlib cimport free, malloc
from libc.string cimport memcpy

cdef void dummy_function(const void **p, size_t *l):
    cdef void *tmp = malloc(17)
    memcpy(tmp, "some test\0 bytes", 17)
    p[0] = tmp
    l[0] = 17

cdef void free_dummy_data(const void *p, size_t l, void *arg):
    free(p)

cpdef getbuf():
    cdef const void *p
    cdef size_t l
    dummy_function(&p, &l)
    return MemBuf_init(p, l, &free_dummy_data, NULL)

ctypedef void dealloc_callback(const void *p, size_t l, void *arg)

cdef class MemBuf:
    cdef const void *p
    cdef size_t l
    cdef dealloc_callback *dealloc_cb_p
    cdef void *dealloc_cb_arg

    def __getbuffer__(self, Py_buffer *view, int flags):
        PyBuffer_FillInfo(view, self, self.p, self.l, 1, flags)
    def __releasebuffer__(self, Py_buffer *view):
        pass

    def __dealloc__(self):
        if self.dealloc_cb_p != NULL:
            self.dealloc_cb_p(self.p, self.l, self.dealloc_cb_arg)

# Call this instead of constructing a MemBuf directly.  The __cinit__
# and __init__ methods can only take Python objects, so the real
# constructor is here.  See:
# https://mail.python.org/pipermail/cython-devel/2012-June/002734.html
cdef MemBuf MemBuf_init(const void *p, size_t l,
                        dealloc_callback *dealloc_cb_p,
                        void *dealloc_cb_arg):
    cdef MemBuf ret = MemBuf()
    ret.p = p
    ret.l = l
    ret.dealloc_cb_p = dealloc_cb_p
    ret.dealloc_cb_arg = dealloc_cb_arg
    return ret

使用上面的(命名test.pyx),您将获得以下行为:

$ python -c 'import test; print repr(memoryview(test.getbuf()).tobytes())'
'some test\x00 bytes\x00'

我不知道是否有更简单的方法.


推荐阅读
  • 详解 Python 的二元算术运算,为什么说减法只是语法糖?[Python常见问题]
    原题|UnravellingbinaryarithmeticoperationsinPython作者|BrettCannon译者|豌豆花下猫(“Python猫 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 我们需要用到一个python强大的库:python-dox直接pipinstallpython-docx在项目中加个赤壁赋.docx的空文件附上完整的python代码fromdoc ... [详细]
  • 丛api的python的简单介绍
    本文目录一览:1、如何使用python利用api获取天气预报 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
author-avatar
w康d
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有