Why Arrow¶
Apache Arrow is a columnar memory model. A column of float64 is a length,
a null bitmap, and a contiguous buffer of little-endian IEEE values. Many
languages can read that buffer without parsing a file.
The piece this library implements is the C Data Interface. It is a stable description of one array in the current process:
| Struct | Role |
|---|---|
ArrowSchema |
Format string, name, metadata, flags, children |
ArrowArray |
Length, null count, offset, buffer pointers |
| Release callback | Frees the buffers the producer allocated |
The producer fills the structs. The consumer reads them. The consumer calls
release when it is done. After that call the struct must not be used, and
release itself is set to null so a second call is obvious.
That is a different job from Arrow IPC. IPC is a stream or a file: a schema message, record batches, optional dictionaries, and a footer. IPC exists so two processes, or a process and a disk, can exchange batches. The C Data Interface exists so two libraries already linked into one process can point at the same bytes. This repository does the second job only, and only for plain numeric columns.
Why a Fortran layer¶
Fortran already stores real(c_double) and integer(c_int32_t) in contiguous
columns. The missing piece is the pair of C structs a non-Fortran library
expects. Linking libarrow just to obtain those structs pulls in a large C++
library for a layout that is intentionally small enough to copy by hand.
gld-arrow-fortran declares the structs with iso_c_binding and fills them.
Export copies a Fortran array into one aligned buffer. Import reads the
structs and returns a Fortran pointer. The original array the caller passed
to export is not aliased by the returned pointer. Fixed-width import adopts
the buffer export allocated, so the bytes are not copied a second time.
What is intentionally missing¶
Strings, lists, structs, unions, maps, and dictionaries need child arrays and
offset buffers. This library rejects n_children /= 0 and a non-null
dictionary pointer. A rank-2 numeric array is not encoded as a fixed-size
list. Its shape is metadata on a single primitive array. See
Techniques.
There is no compression, no dictionary encoding, and no device pointer. The buffers are CPU memory.
Little-endian numeric values¶
The Arrow columnar format stores multi-byte numbers little-endian. On a
little-endian host that is the same order as a Fortran integer(c_int32_t)
or real(c_double), so export can copy the bytes as they sit. A big-endian
host is rejected with ARROW_ERR_ENDIAN rather than silently swapped. This
machine, and the CI runner, are little-endian. The big-endian branch is not
executed by the tests.
Bool is the exception to a raw copy. Fortran logical(c_bool) is one byte
per value. Arrow stores bools as bits, least-significant bit first, in the
value buffer. Export packs. Import unpacks.
A stable boundary¶
The benefit of stopping at the C Data Interface is a boundary other Arrow
consumers already understand. They see a primitive format string, two
buffers, a length, and a release function. They do not need a Fortran
compiler. This library does not need their allocator except for malloc,
aligned_alloc, and free from the system C library.