mirror of
https://github.com/pybind/pybind11.git
synced 2026-04-20 14:59:27 +00:00
Fix buffer_info for ctypes buffers (pybind#2502) (#2503)
* tests: New test for ctypes buffers (pybind#2502) * fix: fix buffer_info segfault on views with no stride (pybind11#2502) * Explicit conversions in buffer_info to make clang happy (pybind#2502) * Another explicit cast in buffer_info constructor for clang (pybind#2502) * Simpler implementation of buffer_info constructor from Py_buffer. * Move test_ctypes_buffer into test_buffers * Comment on why view->strides may be NULL (and fix some whitespace) * Use c_strides() instead of zero when view->strides is NULL. c_strides and f_strides are moved from numpy.h (py::array) to buffer_info.h (py::detail) so they can be used from the buffer_info Py_buffer constructor. * Increase ctypes buffer test coverage in test_buffers. * Split ctypes tests and skip one which is broken in PyPy2.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io
|
||||
import struct
|
||||
import ctypes
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -107,3 +108,55 @@ def test_selective_readonly_buffer():
|
||||
memoryview(buf)[0] = b'\0' if env.PY2 else 0
|
||||
with pytest.raises(TypeError):
|
||||
io.BytesIO(b'1').readinto(buf)
|
||||
|
||||
|
||||
def test_ctypes_array_1d():
|
||||
char1d = (ctypes.c_char * 10)()
|
||||
int1d = (ctypes.c_int * 15)()
|
||||
long1d = (ctypes.c_long * 7)()
|
||||
|
||||
for carray in (char1d, int1d, long1d):
|
||||
info = m.get_buffer_info(carray)
|
||||
assert info.itemsize == ctypes.sizeof(carray._type_)
|
||||
assert info.size == len(carray)
|
||||
assert info.ndim == 1
|
||||
assert info.shape == [info.size]
|
||||
assert info.strides == [info.itemsize]
|
||||
assert not info.readonly
|
||||
|
||||
|
||||
def test_ctypes_array_2d():
|
||||
char2d = ((ctypes.c_char * 10) * 4)()
|
||||
int2d = ((ctypes.c_int * 15) * 3)()
|
||||
long2d = ((ctypes.c_long * 7) * 2)()
|
||||
|
||||
for carray in (char2d, int2d, long2d):
|
||||
info = m.get_buffer_info(carray)
|
||||
assert info.itemsize == ctypes.sizeof(carray[0]._type_)
|
||||
assert info.size == len(carray) * len(carray[0])
|
||||
assert info.ndim == 2
|
||||
assert info.shape == [len(carray), len(carray[0])]
|
||||
assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
|
||||
assert not info.readonly
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
"env.PYPY and env.PY2", reason="PyPy2 bytes buffer not reported as readonly"
|
||||
)
|
||||
def test_ctypes_from_buffer():
|
||||
test_pystr = b"0123456789"
|
||||
for pyarray in (test_pystr, bytearray(test_pystr)):
|
||||
pyinfo = m.get_buffer_info(pyarray)
|
||||
|
||||
if pyinfo.readonly:
|
||||
cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
|
||||
cinfo = m.get_buffer_info(cbytes)
|
||||
else:
|
||||
cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
|
||||
cinfo = m.get_buffer_info(cbytes)
|
||||
|
||||
assert cinfo.size == pyinfo.size
|
||||
assert cinfo.ndim == pyinfo.ndim
|
||||
assert cinfo.shape == pyinfo.shape
|
||||
assert cinfo.strides == pyinfo.strides
|
||||
assert not cinfo.readonly
|
||||
|
||||
Reference in New Issue
Block a user