目前所有相關的 APIPy_buffer都被排除在有限的 API 之外。不能Py_buffer從具有有限 API 的 C 擴展中使用,也不能使用穩定的 ABI(應用程式二進制介面)定義具有緩沖區支持的堆型別。
缺乏Py_buffer支持阻止了像 NumPy 或 Pillow 這樣的突出專案使用有限的 API 并生成 abi3 二進制輪。公平地說,這并不是這些專案尚未采用穩定版 abi3 的唯一原因。仍然Py_buffer是必要但非充分條件。穩定的 abi3 支持將使 NumPy 堆疊能夠構建適用于任何 Python 版本 3.11 <= 和 < 4.0 的二進制輪。
受限 API 不包括任何參考Py_buffer以下內容的C API :
- 8個
PyBuffer_*()功能 - 21個
PyBUF_*常數 PyMemoryView_FromBuffer()PyObject_GetBufferPy_bf_getbuffer/Py_bf_releasebuffer型別插槽PyBufferProcs
添加Py_buffer到穩定的 API 中應該不會非常復雜。它所需要的只是一個不透明的 struct 定義Py_buffer、一個分配函式、一個自由函式和一堆 getter 和 setter。困難的部分是弄清楚需要哪些 getter 和 setter,以及 getter 和 setter 必須公開多少結構成員。我建議首先從 NumPy、Pillow 和 Cython 開發人員那里獲得反饋。
原型
typedef struct bufferinfo Py_buffer;
/* allocate a new Py_buffer object on the heap and initialize all members to
NULL / 0
*/
Py_buffer*
PyBuffer_New()
{
Py_buffer *view = PyMem_Calloc(1, sizeof(Py_buffer));
if (view == NULL) {
PyErr_NoMemory();
}
return view;
}
/* convenience function */
Py_buffer*
PyBuffer_NewEx(PyObject *obj, void *buf, Py_ssize_t len, Py_ssize_t itemsize,
int readonly, int ndim, char *format, Py_ssize_t *shape,
Py_ssize_t *strides, Py_ssize_t *suboffsets, void *internal)
{
...
}
/* release and free buffer */
void
PyBuffer_Free(Py_buffer *view)
{
if (view != NULL) {
PyBuffer_Release(view);
PyMem_Free(view);
}
}
uj5u.com熱心網友回復:
Py_buffer.shape 需要一個 Py_ssize_t* 指標。不方便。例如,陣列模塊使用:
static int
array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
{
...
if ((flags & PyBUF_ND)==PyBUF_ND) {
view->shape = &((PyVarObject*)self)->ob_size;
}
...
return 0;
}
IIRC 形狀、步幅和子偏移量都是 ndims 長度的陣列。
如果我們要求用戶指定 ndims 的值并且不允許他們之后更改該值,我們可以優化分配。PyBuffer_New(int ndims) 然后將分配 size 的視圖sizeof(Py_buffer) (3 * ndims * sizeof(Py_ssize_t *))。這將為我們提供足夠的空間來memcpy()在 Py_buffer 結構之后將引數整形、步幅和子偏移量放入記憶體中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/321700.html
