Skip to content

Commit 039762f

Browse files
committed
Implement PyMemoryView_GetContiguous
1 parent f20c081 commit 039762f

File tree

3 files changed

+76
-17
lines changed

3 files changed

+76
-17
lines changed

graalpython/com.oracle.graal.python.cext/src/memoryobject.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ PyObject* PyMemoryView_FromObject(PyObject *v) {
5959

6060
/* called back from the above upcall only if the object was native */
6161
PyObject* PyTruffle_MemoryViewFromObject(PyObject *v) {
62-
// TODO resource management
63-
Py_buffer buffer;
62+
Py_buffer buffer;
6463
if (PyObject_CheckBuffer(v)) {
6564
PyObject *ret;
6665
if (PyObject_GetBuffer(v, &buffer, PyBUF_FULL_RO) < 0) {
@@ -92,30 +91,34 @@ PyObject* PyMemoryView_FromBuffer(Py_buffer *buffer) {
9291
releasefn = pb->bf_releasebuffer;
9392
}
9493
}
95-
return polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_MemoryViewFromBuffer",
96-
buffer,
97-
native_to_java(buffer->obj),
98-
releasefn,
99-
buffer->len,
100-
buffer->readonly,
101-
buffer->itemsize,
102-
polyglot_from_string(buffer->format ? buffer->format : "B", "ascii"),
103-
buffer->ndim,
104-
polyglot_from_i8_array(buffer->buf, buffer->len),
105-
buffer->shape ? polyglot_from_size_array(buffer->shape, ndim) : NULL,
106-
buffer->strides ? polyglot_from_size_array(buffer->strides, ndim) : NULL,
107-
buffer->suboffsets ? polyglot_from_size_array(buffer->suboffsets, ndim) : NULL);
94+
return polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_MemoryViewFromBuffer",
95+
buffer,
96+
native_to_java(buffer->obj),
97+
releasefn,
98+
buffer->len,
99+
buffer->readonly,
100+
buffer->itemsize,
101+
polyglot_from_string(buffer->format ? buffer->format : "B", "ascii"),
102+
buffer->ndim,
103+
polyglot_from_i8_array(buffer->buf, buffer->len),
104+
buffer->shape ? polyglot_from_size_array(buffer->shape, ndim) : NULL,
105+
buffer->strides ? polyglot_from_size_array(buffer->strides, ndim) : NULL,
106+
buffer->suboffsets ? polyglot_from_size_array(buffer->suboffsets, ndim) : NULL);
108107
}
109108

110-
PyObject *PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
111-
{
109+
PyObject *PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags) {
112110
assert(mem != NULL);
113111
assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
114112
int readonly = (flags == PyBUF_WRITE) ? 0 : 1;
115113
return polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_MemoryViewFromBuffer",
116114
NULL, NULL, NULL, size, readonly, 1, polyglot_from_string("B", "ascii"), 1, polyglot_from_i8_array((int8_t*)mem, size), NULL, NULL, NULL);
117115
}
118116

117+
UPCALL_ID(PyMemoryView_GetContiguous)
118+
PyObject* PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order) {
119+
return UPCALL_CEXT_O(_jls_PyMemoryView_GetContiguous, native_to_java(obj), buffertype, (int)order);
120+
}
121+
119122
/* Macros taken from CPython */
120123
/* Memoryview buffer properties */
121124
#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_memoryview.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,32 @@ def compile_module(self, name):
224224
cmpfunc=unhandled_error_compare_with_message,
225225
)
226226

227+
test_memoryview_getcontiguous = CPyExtFunction(
228+
lambda args: args[1],
229+
lambda: [
230+
(bytearray(b'12345678'), b'12345678'),
231+
(memoryview(b'12345678'), b'12345678'),
232+
(memoryview(b'12345678')[::2], b'1357'),
233+
(memoryview(b'12345678abcd').cast('i')[::2], b'1234abcd'),
234+
],
235+
code='''
236+
static PyObject* test_getcontiguous(PyObject* obj, PyObject* expected) {
237+
PyObject *mv = PyMemoryView_GetContiguous(obj, PyBUF_READ, 'C');
238+
if (!mv)
239+
return NULL;
240+
Py_buffer *view = PyMemoryView_GET_BUFFER(mv);
241+
PyObject *bytes = PyBytes_FromStringAndSize(view->buf, view->len);
242+
Py_DECREF(mv);
243+
return bytes;
244+
}
245+
''',
246+
resultspec='O',
247+
argspec='OO',
248+
arguments=["PyObject* order", "PyObject* expected"],
249+
callfunction="test_getcontiguous",
250+
cmpfunc=unhandled_error_compare_with_message,
251+
)
252+
227253
test_memoryview_slice = CPyExtFunction(
228254
lambda args: bytes((5, 6, 255, 128, 99))[args[0]][args[1]][args[2]],
229255
lambda: list(itertools.product(slices, slices, range(-2, 5))),

graalpython/lib-graalpython/python_cext.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,36 @@ def PyUnicode_Replace(s, substr, replstr, count):
800800
return s.replace(substr, replstr, count)
801801

802802

803+
##################### MEMORY_VIEW
804+
def PyMemoryView_GetContiguous(obj, buffertype, order_int):
805+
PyBUF_READ = 0x100
806+
PyBUF_WRITE = 0x200
807+
assert buffertype == PyBUF_READ or buffertype == PyBUF_WRITE
808+
order = chr(order_int)
809+
assert order == 'C' or order == 'F' or order == 'A'
810+
mv = memoryview(obj)
811+
release = True
812+
try:
813+
if buffertype == PyBUF_WRITE and mv.readonly:
814+
raise BufferError("underlying buffer is not writable")
815+
if mv.contiguous:
816+
release = False
817+
return mv
818+
if buffertype == PyBUF_WRITE:
819+
raise BufferError("writable contiguous buffer requested for a non-contiguous object.")
820+
mv_bytes = memoryview(mv.tobytes(order))
821+
if mv.format == 'B':
822+
return mv_bytes
823+
else:
824+
try:
825+
return mv_bytes.cast(mv.format)
826+
finally:
827+
mv_bytes.release()
828+
finally:
829+
if release:
830+
mv.release()
831+
832+
803833
##################### CAPSULE
804834

805835

0 commit comments

Comments
 (0)