我正在使用一个C库,它重复调用用户提供的函数指针以获取更多数据.我想以这样的方式,Python实现该回调可以返回任何合理的数据类型写一个用Cython包装一样str
,bytearray
,内存映射文件等(具体而言,支持缓冲接口).到目前为止我所拥有的是:
from cpython.buffer cimport PyBUF_SIMPLE
from cpython.buffer cimport Py_buffer
from cpython.buffer cimport PyObject_GetBuffer
from cpython.buffer cimport PyBuffer_Release
from libc.string cimport memmove
cdef class _callback:
cdef public object callback
cdef public object data
cdef uint16_t GetDataCallback(void * userdata,
uint32_t wantlen, unsigned char * data,
uint32_t * gotlen):
cdef Py_buffer gotdata
box = <_callback> userdata
gotdata_object = box.callback(box.data, wantlen)
if not PyObject_CheckBuffer(gotdata_object):
# sulk
return 1
try:
PyObject_GetBuffer(gotdata_object, &gotdata, PyBUF_SIMPLE)
if not (0 < gotdata.len <= …
Run Code Online (Sandbox Code Playgroud) 当我尝试将ctypes数组用作numpy数组时,我收到以下警告消息:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes, numpy
>>> TenByteBuffer = ctypes.c_ubyte * 10
>>> a = TenByteBuffer()
>>> b = numpy.ctypeslib.as_array(a)
C:\Python27\lib\site-packages\numpy\ctypeslib.py:402: RuntimeWarning: Item size
computed from the PEP 3118 buffer format string does not match the actual item s
ize.
return array(obj, copy=False)
>>> b
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)
但是代码似乎正在起作用.忽略这个警告是不是一个坏主意?
背景:我正在调用一个实时生成数据的C …
我正在扩展我们的库(支持Python 2.7)中的类以支持PEP 3118,后者已经被反向移植到2.7.
从文档中,我需要初始化tp_as_buffer
字段以指向a PyBufferProcs
.但是,从2.7的文档中,此结构的描述仅包含旧缓冲区协议的条目.从来源,我收集的是
PyBufferProcs
对新协议(一些其他的项目bf_getbuffer
和bf_releasebuffer
).
问题仍然存在:
我是否必须做一些特别的事情来告诉Python这些新条目是否有效?
我是否必须填写旧协议的条目?(例如,2.7的文档说明bf_getsegcount
可能不为空.但如果我支持PEP 3118,则不应使用此条目.)
数组上的python文档清楚地表明该数组符合缓冲区接口.它甚至建议不使用buffer_info()方法.但是当我尝试使用PyObject_GetBuffer()从C/C++代码中获取Py_Buffer或使用python的memoryview时,我得到了一个失败.
例如,在python中(我使用的是2.7版):
>>> a = array.array('c')
>>> memoryview(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot make memory view because object does not have the buffer interface
Run Code Online (Sandbox Code Playgroud)
实际上,当我搜索python的代码库时,只有bytearrayobject(bytearray),memoryobject(memoryview)和stringobject(str)在它们上面设置了所需的Py_TPFLAGS_HAVE_NEWBUFFER标志.据我了解,文档是错误的; 数组不支持缓冲区接口.
我可以使用支持缓冲区接口的bytearray,问题是我需要数组的实用fromfile()方法来读取我可以在我的C/C++代码中使用的缓冲区.
有没有一种方法可以让我将文件读入缓冲区并使用C代码中的缓冲区,而不涉及内存副本?(我想处理大二进制文件,复制是一个不太理想的选择).
我对python中的术语'缓冲接口'很困惑.说"暴露其底层内存结构的python对象"可以用某个例子来解释是什么意思.提前谢谢
我对使用缓冲区协议在python,numpy和cython之间传递二进制数据感兴趣。查看PEP 3118,似乎在结构字符串语法中添加了一些内容,从而增加了对诸如命名字段和嵌套结构之类的有用功能的支持。
但是,似乎在这三个位置中,对缓冲区语法的所有范围的支持都受到限制。例如,假设我具有以下cython结构:
ctypedef packed struct ImageComp:
uint32_t width
uint32_t height
uint8_t *pixels
#Here is the appropriate struct format string representation
IMAGE_FORMAT = b'T{L:width:L:height:&B:pixels:}'
Run Code Online (Sandbox Code Playgroud)
尝试如下提取PEP-3118兼容字节字符串
cdef void *image_temp = malloc(sizeof(ImageComp))
IMAGE_SIZE = sizeof(ImageComp)
IMAGE_FORMAT = (<ImageComp[:1]>image_temp)._format
IMAGE_DTYPE = np.asarray(<ImageComp[:1]>image_temp).dtype
free(image_temp)
Run Code Online (Sandbox Code Playgroud)
失败,并显示以下错误消息:
Invalid base type for memoryview slice: ImageComp
因为键入的内存视图如果包含指针,则无法创建。
同样,view.array
使用我的自定义字符串或使用python struct
模块的calcsize
函数创建时,会发出类似的警告struct.error: bad char in struct format
。
我可以Py_buffer
按照此处所述手动创建和填充对象,但是尝试将其转换为具有np.asarray
yields 的numpy数组ValueError: 'T{L:width:L:height:&B:pixels:}' is not a valid PEP …
这个问题与我之前提出的一个问题有关。即这一项,如果有人有兴趣。基本上,我想要做的是使用Py_buffer
包装在memoryview
-object 中的 C 数组向 Python 公开。我已经使用PyBuffer_FillInfo
(工作 = 我可以在 Python 中操作数据并将其写入 C 中的标准输出),但是如果我尝试滚动我自己的缓冲区,我会在 C 函数返回后得到一个段错误。
我需要创建自己的缓冲区,因为 PyBuffer_FillInfo 假定格式为 char,使 itemsize 字段为 1。我需要能够提供大小为 1、2、4 和 8 的项目。
一些代码,这是一个工作示例:
Py_buffer *buf = (Py_buffer *) malloc(sizeof(*buf));
int r = PyBuffer_FillInfo(buf, NULL, malloc(sizeof(char) * 4), 4, 0, PyBUF_CONTIG);
PyObject *mv = PyMemoryView_FromBuffer(buf);
//Pack the memoryview object into an argument list and call the Python function
for (blah)
printf("%c\n", *buf->buf++); //this prints the values i set …
Run Code Online (Sandbox Code Playgroud) 目标:使用 Cython 从 2D C++ 字符数组获取 Memoryview。
一点背景:
我有一个本机 C++ 库,它生成一些数据并通过 a 返回char**
到 Cython 世界。数组在库中的初始化和操作大约是这样的:
struct Result_buffer{
char** data_pointer;
int length = 0;
Result_buffer( int row_capacity) {
data_pointer; = new char*[row_capacity];
return arr;
}
// the actual data is appended row by row
void append_row(char* row_data) {
data_pointer[length] = row_data;
length++;
}
}
Run Code Online (Sandbox Code Playgroud)
所以我们基本上得到了一个嵌套子数组的数组。
旁注:
- 每行具有相同的列数
- 行可以共享内存,即指向相同的 row_data
目标是最好将此数组与内存视图一起使用,而无需昂贵的内存复制。
使用 Cython 数组和内存视图:
这是应该使用生成的数据的 .pyx 文件
from cython cimport view
cimport numpy as np …
Run Code Online (Sandbox Code Playgroud) 我想要一种方法来生成红色,绿色或蓝色的小RGB方形图像.它应该产生坚固的色块,但PIL输出的图像非常奇怪.为什么?
import numpy as np
from PIL import Image
class MakeSquares():
def __init__(self):
self.num_rows = 3
self.num_cols = 3
self.colourmap = {'red': [255, 0, 0],
'green': [0, 255, 0],
'blue': [0, 0, 255]}
def generateExample(self, label):
arr = []
colour = label
colour_array = self.colourmap[colour]
for i in range(0, self.num_rows):
sarr = []
for j in range(0, self.num_cols):
sarr.append(colour_array)
arr.append(sarr)
narr = np.asarray(arr)
return narr
test = MakeSquares()
t = test.generateExample("red")
print t
testimage = Image.fromarray(t, "RGB")
testimage.save("testimage.jpg")
Run Code Online (Sandbox Code Playgroud)
此代码返回以下numpy数组:
[[[255 …
Run Code Online (Sandbox Code Playgroud) pep3118 ×9
python ×8
pybuffer ×4
cython ×3
numpy ×3
buffer ×2
python-3.x ×2
arrays ×1
cpython ×1
ctypes ×1
image ×1
memoryview ×1
python-2.7 ×1
python-c-api ×1
warnings ×1