Skip to content

Commit c17e314

Browse files
committed
Wrap _PyBytes_Resize for improved usability
The `_PyBytes_Resize` function is helpful for resizing a `bytes` object after it is allocated. When the underlying `bytes` object only has one reference to it, the function can potentially use realloc to shrink or grow the allocation in-place. While the function signature of `_PyBytes_Resize` makes sense, it is a little unwieldly when used directly in Cython. To smooth this out a bit, use a macro to wrap calls to `_PyBytes_Resize`. This allows us to work with `PyObject*`s, which Cython handles well, instead of `PyObject**`s, which Cython handles awkwardly. The end result is a function from Cython's perspective, which is easy to use, and one under-the-hood that simply massages our input arguments into something `_PyBytes_Resize` expects.
1 parent 0bfafed commit c17e314

File tree

3 files changed

+24
-18
lines changed

3 files changed

+24
-18
lines changed

numcodecs/blosc.pyx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,21 @@ from cpython.buffer cimport PyBuffer_IsContiguous
1313
from cpython.bytes cimport (
1414
PyBytes_AS_STRING,
1515
PyBytes_FromStringAndSize,
16-
_PyBytes_Resize,
1716
)
1817
from cpython.memoryview cimport PyMemoryView_GET_BUFFER
19-
from cpython.object cimport PyObject
2018

2119

2220
from .compat import ensure_contiguous_ndarray
2321
from .abc import Codec
2422

2523

24+
cdef extern from *:
25+
"""
26+
#define PyBytes_RESIZE(b, n) _PyBytes_Resize(&b, n)
27+
"""
28+
int PyBytes_RESIZE(object b, Py_ssize_t n) except -1
29+
30+
2631
cdef extern from "blosc.h":
2732
cdef enum:
2833
BLOSC_MAX_OVERHEAD,
@@ -276,7 +281,6 @@ def compress(source, char* cname, int clevel, int shuffle=SHUFFLE,
276281
size_t nbytes, itemsize
277282
int cbytes
278283
bytes dest
279-
PyObject* dest_objptr
280284
char* dest_ptr
281285

282286
# check valid cname early
@@ -356,9 +360,7 @@ def compress(source, char* cname, int clevel, int shuffle=SHUFFLE,
356360
raise RuntimeError('error during blosc compression: %d' % cbytes)
357361

358362
# resize after compression
359-
dest_objptr = <PyObject*>dest
360-
_PyBytes_Resize(&dest_objptr, cbytes)
361-
dest = <bytes>dest_objptr
363+
PyBytes_RESIZE(dest, cbytes)
362364

363365
return dest
364366

numcodecs/lz4.pyx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@ from cpython.buffer cimport PyBuffer_IsContiguous
1111
from cpython.bytes cimport (
1212
PyBytes_AS_STRING,
1313
PyBytes_FromStringAndSize,
14-
_PyBytes_Resize,
1514
)
1615
from cpython.memoryview cimport PyMemoryView_GET_BUFFER
17-
from cpython.object cimport PyObject
1816

1917
from ._utils cimport store_le32, load_le32
2018
from .compat import ensure_contiguous_ndarray
2119
from .abc import Codec
2220

2321

22+
cdef extern from *:
23+
"""
24+
#define PyBytes_RESIZE(b, n) _PyBytes_Resize(&b, n)
25+
"""
26+
int PyBytes_RESIZE(object b, Py_ssize_t n) except -1
27+
28+
2429
cdef extern from "lz4.h":
2530

2631
const char* LZ4_versionString() nogil
@@ -74,7 +79,6 @@ def compress(source, int acceleration=DEFAULT_ACCELERATION):
7479
const Py_buffer* source_pb
7580
const char* source_ptr
7681
bytes dest
77-
PyObject* dest_objptr
7882
char* dest_ptr
7983
char* dest_start
8084
int source_size, dest_size, compressed_size
@@ -115,9 +119,7 @@ def compress(source, int acceleration=DEFAULT_ACCELERATION):
115119

116120
# resize after compression
117121
compressed_size += sizeof(uint32_t)
118-
dest_objptr = <PyObject*>dest
119-
_PyBytes_Resize(&dest_objptr, compressed_size)
120-
dest = <bytes>dest_objptr
122+
PyBytes_RESIZE(dest, compressed_size)
121123

122124
return dest
123125

numcodecs/zstd.pyx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@ from cpython.buffer cimport PyBuffer_IsContiguous
99
from cpython.bytes cimport (
1010
PyBytes_AS_STRING,
1111
PyBytes_FromStringAndSize,
12-
_PyBytes_Resize,
1312
)
1413
from cpython.memoryview cimport PyMemoryView_GET_BUFFER
15-
from cpython.object cimport PyObject
1614

1715
from .compat import ensure_contiguous_ndarray
1816
from .abc import Codec
1917

2018

19+
cdef extern from *:
20+
"""
21+
#define PyBytes_RESIZE(b, n) _PyBytes_Resize(&b, n)
22+
"""
23+
int PyBytes_RESIZE(object b, Py_ssize_t n) except -1
24+
25+
2126
cdef extern from "zstd.h":
2227

2328
unsigned ZSTD_versionNumber() nogil
@@ -100,7 +105,6 @@ def compress(source, int level=DEFAULT_CLEVEL, bint checksum=False):
100105
const char* source_ptr
101106
size_t source_size, dest_size, compressed_size
102107
bytes dest
103-
PyObject* dest_objptr
104108
char* dest_ptr
105109

106110
# check level
@@ -151,9 +155,7 @@ def compress(source, int level=DEFAULT_CLEVEL, bint checksum=False):
151155
raise RuntimeError('Zstd compression error: %s' % error)
152156

153157
# resize after compression
154-
dest_objptr = <PyObject*>dest
155-
_PyBytes_Resize(&dest_objptr, compressed_size)
156-
dest = <bytes>dest_objptr
158+
PyBytes_RESIZE(dest, compressed_size)
157159

158160
return dest
159161

0 commit comments

Comments
 (0)