From 1e87fb9f18c24702c2707d46c2c8c6b51416c6f1 Mon Sep 17 00:00:00 2001 From: Barak Ugav Date: Sun, 24 Aug 2025 22:09:35 +0300 Subject: [PATCH] Add as_ffi_ptr to NDArray --- src/blosc2/__init__.py | 1 + src/blosc2/blosc2_ext.pyx | 7 +++++++ src/blosc2/ndarray.py | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/src/blosc2/__init__.py b/src/blosc2/__init__.py index 1d21e07af..28998bb8b 100644 --- a/src/blosc2/__init__.py +++ b/src/blosc2/__init__.py @@ -328,6 +328,7 @@ class Tuner(Enum): arctan, arctan2, arctanh, + array_from_ffi_ptr, conj, contains, cos, diff --git a/src/blosc2/blosc2_ext.pyx b/src/blosc2/blosc2_ext.pyx index def2cb8bc..69fe0b96f 100644 --- a/src/blosc2/blosc2_ext.pyx +++ b/src/blosc2/blosc2_ext.pyx @@ -2614,6 +2614,9 @@ cdef class NDArray: if self.array.shape[0] == 1 and self.ndim == 1: self.array.ndim = 0 + def as_ffi_ptr(self): + return PyCapsule_New(self.array, "b2nd_array_t*", NULL) + cdef udf_udata *_fill_udf_udata(self, func_id, inputs_id): cdef udf_udata *udata = malloc(sizeof(udf_udata)) udata.py_func = malloc(strlen(func_id) + 1) @@ -2900,6 +2903,10 @@ def asarray(ndarray, chunks, blocks, **kwargs): return ndarray +def array_from_ffi_ptr(array_ptr): + array = PyCapsule_GetPointer(array_ptr, "b2nd_array_t*") + return blosc2.NDArray(_schunk=PyCapsule_New(array.sc, "blosc2_schunk*", NULL), + _array=array_ptr) def ndarray_from_cframe(cframe, copy=False): cdef Py_buffer buf diff --git a/src/blosc2/ndarray.py b/src/blosc2/ndarray.py index 5fa7ccda4..d9d56f42f 100644 --- a/src/blosc2/ndarray.py +++ b/src/blosc2/ndarray.py @@ -2169,6 +2169,24 @@ def sort(self, order: str | list[str] | None = None, **kwargs: Any) -> NDArray: """ return sort(self, order, **kwargs) + def as_ffi_ptr(self): + """Returns the pointer to the raw FFI blosc2::b2nd_array_t object. + + This function is useful for passing the array to C functions. + """ + return super().as_ffi_ptr() + + +def array_from_ffi_ptr(array_ptr) -> NDArray: + """ + Create an NDArray from a raw FFI pointer. + + This function is useful for passing arrays across FFI boundaries. + This function move the ownership of the underlying `b2nd_array_t*` object to the new NDArray, and it will be freed + when the object is destroyed. + """ + return blosc2_ext.array_from_ffi_ptr(array_ptr) + def sin(ndarr: NDArray | NDField | blosc2.C2Array | blosc2.LazyExpr, /) -> blosc2.LazyExpr: """