Skip to content

Commit 5872dda

Browse files
Copilotjpfeuffer
andcommitted
Set .base to self for reference returns, verify in tests
Fixed the .base attribute handling as requested: - For reference returns: Explicitly set (<numpy.ndarray>arr).base = self to keep owner alive - For value returns: ArrayWrapper automatically set as .base by buffer protocol (already working) - Updated test to verify .base is the owner object (not memoryview) This ensures proper lifetime management - the numpy array keeps the C++ object alive to prevent premature garbage collection. Commit addresses comment 3679292583 Co-authored-by: jpfeuffer <8102638+jpfeuffer@users.noreply.github.com>
1 parent b2e1d0c commit 5872dda

File tree

3 files changed

+8
-4
lines changed

3 files changed

+8
-4
lines changed

autowrap/ConversionProvider.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,8 +2248,7 @@ def output_conversion(
22482248
if cpp_type.is_ref:
22492249
# Reference return: Use Cython memory view for zero-copy access
22502250
# For const references: set readonly flag
2251-
# The memory view object automatically becomes the base when we call numpy.asarray()
2252-
# We need to ensure 'self' (the owner) is kept alive by the memory view
2251+
# Explicitly set .base to self to keep the owner alive (not the memory view)
22532252
if cpp_type.is_const:
22542253
code = Code().add(
22552254
"""
@@ -2258,6 +2257,7 @@ def output_conversion(
22582257
|cdef $ctype[:] _view_$output_py_var = <$ctype[:_size_$output_py_var]>$input_cpp_var.data()
22592258
|cdef object $output_py_var = numpy.asarray(_view_$output_py_var)
22602259
|$output_py_var.setflags(write=False)
2260+
|(<numpy.ndarray>$output_py_var).base = self
22612261
""",
22622262
dict(
22632263
input_cpp_var=input_cpp_var,
@@ -2272,6 +2272,7 @@ def output_conversion(
22722272
|cdef size_t _size_$output_py_var = $input_cpp_var.size()
22732273
|cdef $ctype[:] _view_$output_py_var = <$ctype[:_size_$output_py_var]>$input_cpp_var.data()
22742274
|cdef object $output_py_var = numpy.asarray(_view_$output_py_var)
2275+
|(<numpy.ndarray>$output_py_var).base = self
22752276
""",
22762277
dict(
22772278
input_cpp_var=input_cpp_var,

tests/test_files/numpy_vector/numpy_vector_wrapper.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ cdef class NumpyVectorTest:
743743
cdef double[:] _view_py_result = <double[:_size_py_result]>_r.data()
744744
cdef object py_result = numpy.asarray(_view_py_result)
745745
py_result.setflags(write=False)
746+
(<numpy.ndarray>py_result).base = self
746747
return py_result
747748

748749
def getMutableRefVector(self):
@@ -754,6 +755,7 @@ cdef class NumpyVectorTest:
754755
cdef size_t _size_py_result = _r.size()
755756
cdef double[:] _view_py_result = <double[:_size_py_result]>_r.data()
756757
cdef object py_result = numpy.asarray(_view_py_result)
758+
(<numpy.ndarray>py_result).base = self
757759
return py_result
758760

759761
def getValueVector(self, size ):

tests/test_numpy_vector_converter.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,10 @@ def test_const_ref_output_is_readonly_view(self, numpy_vector_module):
7474
with pytest.raises(ValueError, match="read-only"):
7575
result[0] = 999.0
7676

77-
# Check base attribute - should be the C++ object or a memory view wrapper
78-
# Memory views keep a reference to the owner to prevent garbage collection
77+
# Check base attribute - should be the C++ object (NumpyVectorTest instance)
78+
# This keeps the owner alive to prevent garbage collection
7979
assert result.base is not None
80+
assert result.base is t, f"Expected .base to be the NumpyVectorTest instance, got {type(result.base).__name__}"
8081

8182
@pytest.mark.skip(reason="Mutable ref views require ensuring C++ object lifetime exceeds view lifetime - needs investigation of reference handling")
8283
def test_mutable_ref_output_is_view(self, numpy_vector_module):

0 commit comments

Comments
 (0)