diff options
author | Matti Picus <matti.picus@gmail.com> | 2021-10-27 23:09:51 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-27 15:09:51 -0500 |
commit | aebf38662647b328e5ac10c52a24202b3a22cf66 (patch) | |
tree | 50e6ad54c9bb64b42b18c67a29f719ae1c5ceb21 /doc/source/reference/c-api | |
parent | f66a76ec2d592c4f44c3f44c596b6d6f581626e5 (diff) | |
download | numpy-aebf38662647b328e5ac10c52a24202b3a22cf66.tar.gz |
MAINT: Only warn for transferred ownership if env variable is set (#20200)
Builds on gh-20194. Fixes breakage of SciPy in https://github.com/scipy/scipy/issues/14917
At some point we could flip the default to "warn" instead of "no warning"
* make warning conditional on NUMPY_WARN_IF_NO_MEM_POLICY
* add test, fix example code
* fixes from review
* typo
Diffstat (limited to 'doc/source/reference/c-api')
-rw-r--r-- | doc/source/reference/c-api/array.rst | 7 | ||||
-rw-r--r-- | doc/source/reference/c-api/data_memory.rst | 37 |
2 files changed, 41 insertions, 3 deletions
diff --git a/doc/source/reference/c-api/array.rst b/doc/source/reference/c-api/array.rst index 6a135fd71..232690486 100644 --- a/doc/source/reference/c-api/array.rst +++ b/doc/source/reference/c-api/array.rst @@ -325,8 +325,7 @@ From scratch should be increased after the pointer is passed in, and the base member of the returned ndarray should point to the Python object that owns the data. This will ensure that the provided memory is not - freed while the returned array is in existence. To free memory as soon - as the ndarray is deallocated, set the OWNDATA flag on the returned ndarray. + freed while the returned array is in existence. .. c:function:: PyObject* PyArray_SimpleNewFromDescr( \ int nd, npy_int const* dims, PyArray_Descr* descr) @@ -1463,7 +1462,9 @@ of the constant names is deprecated in 1.7. .. c:macro:: NPY_ARRAY_OWNDATA - The data area is owned by this array. + The data area is owned by this array. Should never be set manually, instead + create a ``PyObject`` wrapping the data and set the array's base to that + object. For an example, see the test in ``test_mem_policy``. .. c:macro:: NPY_ARRAY_ALIGNED diff --git a/doc/source/reference/c-api/data_memory.rst b/doc/source/reference/c-api/data_memory.rst index c17f98a2c..11a37adc4 100644 --- a/doc/source/reference/c-api/data_memory.rst +++ b/doc/source/reference/c-api/data_memory.rst @@ -119,3 +119,40 @@ For an example of setting up and using the PyDataMem_Handler, see the test in operations that might cause new allocation events (such as the creation/destruction numpy objects, or creating/destroying Python objects which might cause a gc) + +What happens when deallocating if there is no policy set +-------------------------------------------------------- + +A rare but useful technique is to allocate a buffer outside NumPy, use +:c:func:`PyArray_NewFromDescr` to wrap the buffer in a ``ndarray``, then switch +the ``OWNDATA`` flag to true. When the ``ndarray`` is released, the +appropriate function from the ``ndarray``'s ``PyDataMem_Handler`` should be +called to free the buffer. But the ``PyDataMem_Handler`` field was never set, +it will be ``NULL``. For backward compatibility, NumPy will call ``free()`` to +release the buffer. If ``NUMPY_WARN_IF_NO_MEM_POLICY`` is set to ``1``, a +warning will be emitted. The current default is not to emit a warning, this may +change in a future version of NumPy. + +A better technique would be to use a ``PyCapsule`` as a base object: + +.. code-block:: c + + /* define a PyCapsule_Destructor, using the correct deallocator for buff */ + void free_wrap(void *capsule){ + void * obj = PyCapsule_GetPointer(capsule, PyCapsule_GetName(capsule)); + free(obj); + }; + + /* then inside the function that creates arr from buff */ + ... + arr = PyArray_NewFromDescr(... buf, ...); + if (arr == NULL) { + return NULL; + } + capsule = PyCapsule_New(buf, "my_wrapped_buffer", + (PyCapsule_Destructor)&free_wrap); + if (PyArray_SetBaseObject(arr, capsule) == -1) { + Py_DECREF(arr); + return NULL; + } + ... |