Skip to content

Commit

Permalink
docs: add examples in cython and C
Browse files Browse the repository at this point in the history
  • Loading branch information
wjones127 committed Oct 1, 2023
1 parent bd02417 commit 6fff484
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 8 deletions.
2 changes: 1 addition & 1 deletion docs/source/format/ADBC.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
ADBC: Arrow Database Connectivity
=================================

Full Documentation on ADBC can be found at `https://arrow.apache.org/adbc/`_.
Full Documentation on ADBC can be found at `https://arrow.apache.org/adbc/`_

Rationale
=========
Expand Down
92 changes: 91 additions & 1 deletion docs/source/format/CDataInterface/PyCapsuleInterface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Non-goals
Comparison to DataFrame Interchange Protocol
--------------------------------------------

:doc:`../../python/interchange_protocol` is another protocol
:doc:`/python/interchange_protocol` is another protocol
in Python that allows for the sharing of data between libraries. This protocol
is complementary to the DataFrame Interchange Protocol. Many of the objects that
implement this protocol will also implement the DataFrame Interchange Protocol.
Expand Down Expand Up @@ -228,3 +228,93 @@ schema transformations.


.. _PyCapsule: https://docs.python.org/3/c-api/capsule.html


Examples
========

Create a PyCapsule
------------------

To create a PyCapsule, use the `PyCapsule_New <https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_New>`_
function. The function must be passed a destructor function that will be called
to release the data the capsule points to. It must first call the release
callback if it is not null, then free the struct.

Below is the code to create a PyCapsule for an ``ArrowSchema``. The code for
``ArrowArray`` and ``ArrowArrayStream`` is similar.

.. tab-set::

.. tab-item:: C

.. code-block:: c
#include <Python.h>
void ReleaseArrowSchemaPyCapsule(PyObject* capsule) {
ArrowSchema* schema =
(ArrowSchema*)PyCapsule_GetPointer(capsule, "arrow_schema");
if (schema->release != NULL) {
schema->release(schema);
}
free(schema);
}
PyObject* MakeArrowSchemaPyCapsule(ArrowSchema* schema) {
return PyCapsule_New(schema, "arrow_schema", ReleaseArrowSchemaPyCapsule);
}
.. tab-item:: Cython

.. code-block:: cython
import cpython
cdef void release_arrow_schema_py_capsule(object schema_capsule):
cdef ArrowSchema* schema = <ArrowSchema*>cpython.PyCapsule_GetPointer(
schema_capsule, 'arrow_schema'
)
if schema.release != NULL:
schema.release(schema)
free(schema)
cdef object make_arrow_schema_py_capsule(ArrowSchema* schema):
return cpython.PyCapsule_New(
<void*>schema, 'arrow_schema', release_arrow_schema_py_capsule
)
Consume a PyCapsule
-------------------

To consume a PyCapsule, use the `PyCapsule_GetPointer <https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_GetPointer>`_ function
to get the pointer to the underlying struct. Import the struct using the your
systems Arrow C Data Interface import function. Only after that should the
capsule be freed.

The below example shows how to consume a PyCapsule for an ``ArrowSchema``. The
code for ``ArrowArray`` and ``ArrowArrayStream`` is similar.

.. tab-set::

.. tab-item:: C

.. code-block:: c
#include <Python.h>
// If the capsule is not an ArrowSchema, will return NULL.
ArrowSchema* GetArrowSchemaPyCapsule(PyObject* capsule) {
return PyCapsule_GetPointer(schema, "arrow_schema");
}
.. tab-item:: Cython

.. code-block:: cython
import cpython
cdef object get_arrow_schema_py_capsule(PyObject* capsule):
return cpython.PyCapsule_GetPointer(capsule, 'arrow_schema')
2 changes: 2 additions & 0 deletions docs/source/python/interchange_protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
.. specific language governing permissions and limitations
.. under the License.
.. _pyarrow-dataframe-interchange-protocol:

Dataframe Interchange Protocol
==============================

Expand Down
8 changes: 2 additions & 6 deletions python/pyarrow/types.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,7 @@ cdef class DataType(_Weakrefable):
Unlike _export_to_c, this will not leak memory if the capsule is not used.
"""
cdef:
ArrowSchema* c_schema = <ArrowSchema*>malloc(sizeof(ArrowSchema))
cdef ArrowSchema* c_schema = <ArrowSchema*>malloc(sizeof(ArrowSchema))
with nogil:
check_status(ExportType(deref(self.type), c_schema))
return cpython.PyCapsule_New(c_schema, 'arrow_schema', &pycapsule_schema_deleter)
Expand Down Expand Up @@ -397,10 +396,7 @@ cdef class DataType(_Weakrefable):


cdef void pycapsule_schema_deleter(object schema_capsule):
cdef:
ArrowSchema* schema
# Do not invoke the deleter on a used/moved capsule
schema = <ArrowSchema*>cpython.PyCapsule_GetPointer(
cdef ArrowSchema* schema = <ArrowSchema*>cpython.PyCapsule_GetPointer(
schema_capsule, 'arrow_schema'
)
if schema.release != NULL:
Expand Down

0 comments on commit 6fff484

Please sign in to comment.