| |
| |
| |
| <!DOCTYPE html> |
| <html class="writer-html5" lang="en" > |
| <head> |
| <meta charset="utf-8" /> |
| |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| |
| <title>The Arrow C data interface — Apache Arrow v3.0.0</title> |
| |
| |
| |
| <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" /> |
| <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> |
| <link rel="stylesheet" href="../_static/theme_overrides.css" type="text/css" /> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <!--[if lt IE 9]> |
| <script src="../_static/js/html5shiv.min.js"></script> |
| <![endif]--> |
| |
| |
| <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> |
| <script src="../_static/jquery.js"></script> |
| <script src="../_static/underscore.js"></script> |
| <script src="../_static/doctools.js"></script> |
| <script src="../_static/language_data.js"></script> |
| |
| <script type="text/javascript" src="../_static/js/theme.js"></script> |
| |
| |
| <link rel="canonical" href="https://arrow.apache.org/docs/format/CDataInterface.html" /> |
| <link rel="index" title="Index" href="../genindex.html" /> |
| <link rel="search" title="Search" href="../search.html" /> |
| <link rel="next" title="The Arrow C stream interface" href="CStreamInterface.html" /> |
| <link rel="prev" title="Integration Testing" href="Integration.html" /> |
|
|
|
|
| <!-- Matomo -->
|
| <script>
|
| var _paq = window._paq = window._paq || [];
|
| /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
| _paq.push(["setDoNotTrack", true]);
|
| _paq.push(["disableCookies"]);
|
| _paq.push(['trackPageView']);
|
| _paq.push(['enableLinkTracking']);
|
| (function() {
|
| var u="https://analytics.apache.org/";
|
| _paq.push(['setTrackerUrl', u+'matomo.php']);
|
| _paq.push(['setSiteId', '20']);
|
| var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
| g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
| })();
|
| </script>
|
| <!-- End Matomo Code -->
|
|
|
| </head> |
| |
| <body class="wy-body-for-nav"> |
| |
| |
| <div class="wy-grid-for-nav"> |
| |
| <nav data-toggle="wy-nav-shift" class="wy-nav-side"> |
| <div class="wy-side-scroll"> |
| <div class="wy-side-nav-search" > |
| |
| |
| |
| <a href="../index.html" class="icon icon-home"> Apache Arrow |
| |
| |
| |
| </a> |
| |
| |
| |
| |
| <div class="version"> |
| 3.0.0 |
| </div> |
| |
| |
| |
| |
| <div role="search"> |
| <form id="rtd-search-form" class="wy-form" action="../search.html" method="get"> |
| <input type="text" name="q" placeholder="Search docs" /> |
| <input type="hidden" name="check_keywords" value="yes" /> |
| <input type="hidden" name="area" value="default" /> |
| </form> |
| </div> |
| |
| |
| </div> |
| |
| |
| <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation"> |
| |
| |
| |
| |
| |
| |
| <p class="caption"><span class="caption-text">Specifications and Protocols</span></p> |
| <ul class="current"> |
| <li class="toctree-l1"><a class="reference internal" href="Versioning.html">Format Versioning and Stability</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="Columnar.html">Arrow Columnar Format</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="Flight.html">Arrow Flight RPC</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="Integration.html">Integration Testing</a></li> |
| <li class="toctree-l1 current"><a class="current reference internal" href="#">The Arrow C data interface</a><ul> |
| <li class="toctree-l2"><a class="reference internal" href="#rationale">Rationale</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#goals">Goals</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#non-goals">Non-goals</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#comparison-with-the-arrow-ipc-format">Comparison with the Arrow IPC format</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="#data-type-description-format-strings">Data type description – format strings</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#examples">Examples</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="#structure-definitions">Structure definitions</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#the-arrowschema-structure">The ArrowSchema structure</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#the-arrowarray-structure">The ArrowArray structure</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#dictionary-encoded-arrays">Dictionary-encoded arrays</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#extension-arrays">Extension arrays</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#memory-management">Memory management</a><ul> |
| <li class="toctree-l4"><a class="reference internal" href="#member-allocation">Member allocation</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#released-structure">Released structure</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#release-callback-semantics-for-consumers">Release callback semantics – for consumers</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#release-callback-semantics-for-producers">Release callback semantics – for producers</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#moving-an-array">Moving an array</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l3"><a class="reference internal" href="#record-batches">Record batches</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="#example-use-case">Example use case</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#c-producer-examples">C producer examples</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#exporting-a-simple-int32-array">Exporting a simple <code class="docutils literal notranslate"><span class="pre">int32</span></code> array</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#exporting-a-struct-float32-utf8-array">Exporting a <code class="docutils literal notranslate"><span class="pre">struct<float32,</span> <span class="pre">utf8></span></code> array</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="#why-two-distinct-structures">Why two distinct structures?</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#updating-this-specification">Updating this specification</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#inspiration">Inspiration</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="CStreamInterface.html">The Arrow C stream interface</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="Other.html">Other Data Structures</a></li> |
| </ul> |
| <p class="caption"><span class="caption-text">Libraries</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../status.html">Implementation Status</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://arrow.apache.org/docs/c_glib/">C/GLib</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../cpp/index.html">C++</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://github.com/apache/arrow/blob/master/csharp/README.md">C#</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://godoc.org/github.com/apache/arrow/go/arrow">Go</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../java/index.html">Java</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://arrow.apache.org/docs/js/">JavaScript</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://github.com/apache/arrow/blob/master/julia/Arrow/README.md">Julia</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://github.com/apache/arrow/blob/master/matlab/README.md">MATLAB</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../python/index.html">Python</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://arrow.apache.org/docs/r/">R</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://github.com/apache/arrow/blob/master/ruby/README.md">Ruby</a></li> |
| <li class="toctree-l1"><a class="reference external" href="https://docs.rs/crate/arrow/">Rust</a></li> |
| </ul> |
| <p class="caption"><span class="caption-text">Development</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/contributing.html">Contributing to Apache Arrow</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/cpp/index.html">C++ Development</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/python.html">Python Development</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/archery.html">Daily Development using Archery</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/crossbow.html">Packaging and Testing with Crossbow</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/docker.html">Running Docker Builds</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/benchmarks.html">Benchmarks</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../developers/documentation.html">Building the Documentation</a></li> |
| </ul> |
| |
| |
| |
| </div> |
| |
| </div> |
| </nav> |
| |
| <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> |
| |
| |
| <nav class="wy-nav-top" aria-label="top navigation"> |
| |
| <i data-toggle="wy-nav-top" class="fa fa-bars"></i> |
| <a href="../index.html">Apache Arrow</a> |
| |
| </nav> |
| |
| |
| <div class="wy-nav-content"> |
| |
| <div class="rst-content"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <div role="navigation" aria-label="breadcrumbs navigation"> |
| |
| <ul class="wy-breadcrumbs"> |
| |
| <li><a href="../index.html" class="icon icon-home"></a> »</li> |
| |
| <li>The Arrow C data interface</li> |
| |
| |
| <li class="wy-breadcrumbs-aside"> |
| |
| |
| <a href="../_sources/format/CDataInterface.rst.txt" rel="nofollow"> View page source</a> |
| |
| |
| </li> |
| |
| </ul> |
| |
| |
| <hr/> |
| </div> |
| <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> |
| <div itemprop="articleBody"> |
| |
| <div class="section" id="the-arrow-c-data-interface"> |
| <span id="c-data-interface"></span><h1>The Arrow C data interface<a class="headerlink" href="#the-arrow-c-data-interface" title="Permalink to this headline">¶</a></h1> |
| <div class="section" id="rationale"> |
| <h2>Rationale<a class="headerlink" href="#rationale" title="Permalink to this headline">¶</a></h2> |
| <p>Apache Arrow is designed to be a universal in-memory format for the representation |
| of tabular (“columnar”) data. However, some projects may face a difficult |
| choice between either depending on a fast-evolving project such as the |
| Arrow C++ library, or having to reimplement adapters for data interchange, |
| which may require significant, redundant development effort.</p> |
| <p>The Arrow C data interface defines a very small, stable set of C definitions |
| that can be easily <em>copied</em> in any project’s source code and used for columnar |
| data interchange in the Arrow format. For non-C/C++ languages and runtimes, |
| it should be almost as easy to translate the C definitions into the |
| corresponding C FFI declarations.</p> |
| <p>Applications and libraries can therefore work with Arrow memory without |
| necessarily using Arrow libraries or reinventing the wheel. Developers can |
| choose between tight integration |
| with the Arrow <em>software project</em> (benefitting from the growing array of |
| facilities exposed by e.g. the C++ or Java implementations of Apache Arrow, |
| but with the cost of a dependency) or minimal integration with the Arrow |
| <em>format</em> only.</p> |
| <div class="section" id="goals"> |
| <h3>Goals<a class="headerlink" href="#goals" title="Permalink to this headline">¶</a></h3> |
| <ul class="simple"> |
| <li><p>Expose an ABI-stable interface.</p></li> |
| <li><p>Make it easy for third-party projects to implement support for (including partial |
| support where sufficient), with little initial investment.</p></li> |
| <li><p>Allow zero-copy sharing of Arrow data between independent runtimes |
| and components running in the same process.</p></li> |
| <li><p>Match the Arrow array concepts closely to avoid the development of |
| yet another marshalling layer.</p></li> |
| <li><p>Avoid the need for one-to-one adaptation layers such as the limited |
| JPype-based bridge between Java and Python.</p></li> |
| <li><p>Enable integration without an explicit dependency (either at compile-time |
| or runtime) on the Arrow software project.</p></li> |
| </ul> |
| <p>Ideally, the Arrow C data interface can become a low-level <em>lingua franca</em> |
| for sharing columnar data at runtime and establish Arrow as the universal |
| building block in the columnar processing ecosystem.</p> |
| </div> |
| <div class="section" id="non-goals"> |
| <h3>Non-goals<a class="headerlink" href="#non-goals" title="Permalink to this headline">¶</a></h3> |
| <ul class="simple"> |
| <li><p>Expose a C API mimicking operations available in higher-level runtimes |
| (such as C++, Java…).</p></li> |
| <li><p>Data sharing between distinct processes or storage persistence.</p></li> |
| </ul> |
| </div> |
| <div class="section" id="comparison-with-the-arrow-ipc-format"> |
| <h3>Comparison with the Arrow IPC format<a class="headerlink" href="#comparison-with-the-arrow-ipc-format" title="Permalink to this headline">¶</a></h3> |
| <p>Pros of the C data interface vs. the IPC format:</p> |
| <ul class="simple"> |
| <li><p>No dependency on Flatbuffers.</p></li> |
| <li><p>No buffer reassembly (data is already exposed in logical Arrow format).</p></li> |
| <li><p>Zero-copy by design.</p></li> |
| <li><p>Easy to reimplement from scratch.</p></li> |
| <li><p>Minimal C definition that can be easily copied into other codebases.</p></li> |
| <li><p>Resource lifetime management through a custom release callback.</p></li> |
| </ul> |
| <p>Pros of the IPC format vs. the data interface:</p> |
| <ul class="simple"> |
| <li><p>Works across processes and machines.</p></li> |
| <li><p>Allows data storage and persistence.</p></li> |
| <li><p>Being a streamable format, the IPC format has room for composing more features |
| (such as integrity checks, compression…).</p></li> |
| <li><p>Does not require explicit C data access.</p></li> |
| </ul> |
| </div> |
| </div> |
| <div class="section" id="data-type-description-format-strings"> |
| <h2>Data type description – format strings<a class="headerlink" href="#data-type-description-format-strings" title="Permalink to this headline">¶</a></h2> |
| <p>A data type is described using a format string. The format string only |
| encodes information about the top-level type; for nested type, child types |
| are described separately. Also, metadata is encoded in a separate string.</p> |
| <p>The format strings are designed to be easily parsable, even from a language |
| such as C. The most common primitive formats have one-character format |
| strings:</p> |
| <table class="docutils align-default"> |
| <colgroup> |
| <col style="width: 31%" /> |
| <col style="width: 47%" /> |
| <col style="width: 22%" /> |
| </colgroup> |
| <thead> |
| <tr class="row-odd"><th class="head"><p>Format string</p></th> |
| <th class="head"><p>Arrow data type</p></th> |
| <th class="head"><p>Notes</p></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">n</span></code></p></td> |
| <td><p>null</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">b</span></code></p></td> |
| <td><p>boolean</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">c</span></code></p></td> |
| <td><p>int8</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">C</span></code></p></td> |
| <td><p>uint8</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">s</span></code></p></td> |
| <td><p>int16</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">S</span></code></p></td> |
| <td><p>uint16</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">i</span></code></p></td> |
| <td><p>int32</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">I</span></code></p></td> |
| <td><p>uint32</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">l</span></code></p></td> |
| <td><p>int64</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">L</span></code></p></td> |
| <td><p>uint64</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">e</span></code></p></td> |
| <td><p>float16</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">f</span></code></p></td> |
| <td><p>float32</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">g</span></code></p></td> |
| <td><p>float64</p></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="docutils align-default"> |
| <colgroup> |
| <col style="width: 21%" /> |
| <col style="width: 64%" /> |
| <col style="width: 15%" /> |
| </colgroup> |
| <thead> |
| <tr class="row-odd"><th class="head"><p>Format string</p></th> |
| <th class="head"><p>Arrow data type</p></th> |
| <th class="head"><p>Notes</p></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">z</span></code></p></td> |
| <td><p>binary</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">Z</span></code></p></td> |
| <td><p>large binary</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">u</span></code></p></td> |
| <td><p>utf-8 string</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">U</span></code></p></td> |
| <td><p>large utf-8 string</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">d:19,10</span></code></p></td> |
| <td><p>decimal128 [precision 19, scale 10]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">d:19,10,NNN</span></code></p></td> |
| <td><p>decimal bitwidth = NNN [precision 19, scale 10]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">w:42</span></code></p></td> |
| <td><p>fixed-width binary [42 bytes]</p></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| <p>Temporal types have multi-character format strings starting with <code class="docutils literal notranslate"><span class="pre">t</span></code>:</p> |
| <table class="docutils align-default"> |
| <colgroup> |
| <col style="width: 21%" /> |
| <col style="width: 64%" /> |
| <col style="width: 15%" /> |
| </colgroup> |
| <thead> |
| <tr class="row-odd"><th class="head"><p>Format string</p></th> |
| <th class="head"><p>Arrow data type</p></th> |
| <th class="head"><p>Notes</p></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tdD</span></code></p></td> |
| <td><p>date32 [days]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">tdm</span></code></p></td> |
| <td><p>date64 [milliseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tts</span></code></p></td> |
| <td><p>time32 [seconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">ttm</span></code></p></td> |
| <td><p>time32 [milliseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">ttu</span></code></p></td> |
| <td><p>time64 [microseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">ttn</span></code></p></td> |
| <td><p>time64 [nanoseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tss:...</span></code></p></td> |
| <td><p>timestamp [seconds] with timezone “…”</p></td> |
| <td><p>(1)</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">tsm:...</span></code></p></td> |
| <td><p>timestamp [milliseconds] with timezone “…”</p></td> |
| <td><p>(1)</p></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tsu:...</span></code></p></td> |
| <td><p>timestamp [microseconds] with timezone “…”</p></td> |
| <td><p>(1)</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">tsn:...</span></code></p></td> |
| <td><p>timestamp [nanoseconds] with timezone “…”</p></td> |
| <td><p>(1)</p></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tDs</span></code></p></td> |
| <td><p>duration [seconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">tDm</span></code></p></td> |
| <td><p>duration [milliseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tDu</span></code></p></td> |
| <td><p>duration [microseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">tDn</span></code></p></td> |
| <td><p>duration [nanoseconds]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">tiM</span></code></p></td> |
| <td><p>interval [months]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">tiD</span></code></p></td> |
| <td><p>interval [days, time]</p></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| <p>Dictionary-encoded types do not have a specific format string. Instead, the |
| format string of the base array represents the dictionary index type, and the |
| value type can be read from the dependent dictionary array (see below |
| “Dictionary-encoded arrays”).</p> |
| <p>Nested types have multiple-character format strings starting with <code class="docutils literal notranslate"><span class="pre">+</span></code>. The |
| names and types of child fields are read from the child arrays.</p> |
| <table class="docutils align-default"> |
| <colgroup> |
| <col style="width: 28%" /> |
| <col style="width: 59%" /> |
| <col style="width: 14%" /> |
| </colgroup> |
| <thead> |
| <tr class="row-odd"><th class="head"><p>Format string</p></th> |
| <th class="head"><p>Arrow data type</p></th> |
| <th class="head"><p>Notes</p></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">+l</span></code></p></td> |
| <td><p>list</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">+L</span></code></p></td> |
| <td><p>large list</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">+w:123</span></code></p></td> |
| <td><p>fixed-sized list [123 items]</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">+s</span></code></p></td> |
| <td><p>struct</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">+m</span></code></p></td> |
| <td><p>map</p></td> |
| <td><p>(2)</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">+ud:I,J,...</span></code></p></td> |
| <td><p>dense union with type ids I,J…</p></td> |
| <td></td> |
| </tr> |
| <tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">+us:I,J,...</span></code></p></td> |
| <td><p>sparse union with type ids I,J…</p></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| <p>Notes:</p> |
| <ol class="arabic simple"> |
| <li><p>The timezone string is appended as-is after the colon character <code class="docutils literal notranslate"><span class="pre">:</span></code>, without |
| any quotes. If the timezone is empty, the colon <code class="docutils literal notranslate"><span class="pre">:</span></code> must still be included.</p></li> |
| <li><p>As specified in the Arrow columnar format, the map type has a single child type |
| named <code class="docutils literal notranslate"><span class="pre">entries</span></code>, itself a 2-child struct type of <code class="docutils literal notranslate"><span class="pre">(key,</span> <span class="pre">value)</span></code>.</p></li> |
| </ol> |
| <div class="section" id="examples"> |
| <h3>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h3> |
| <ul class="simple"> |
| <li><p>A dictionary-encoded <code class="docutils literal notranslate"><span class="pre">decimal128(precision</span> <span class="pre">=</span> <span class="pre">12,</span> <span class="pre">scale</span> <span class="pre">=</span> <span class="pre">5)</span></code> array |
| with <code class="docutils literal notranslate"><span class="pre">int16</span></code> indices has format string <code class="docutils literal notranslate"><span class="pre">s</span></code>, and its dependent dictionary |
| array has format string <code class="docutils literal notranslate"><span class="pre">d:12,5</span></code>.</p></li> |
| <li><p>A <code class="docutils literal notranslate"><span class="pre">list<uint64></span></code> array has format string <code class="docutils literal notranslate"><span class="pre">+l</span></code>, and its single child |
| has format string <code class="docutils literal notranslate"><span class="pre">L</span></code>.</p></li> |
| <li><p>A <code class="docutils literal notranslate"><span class="pre">struct<ints:</span> <span class="pre">int32,</span> <span class="pre">floats:</span> <span class="pre">float32></span></code> has format string <code class="docutils literal notranslate"><span class="pre">+s</span></code>; its two |
| children have names <code class="docutils literal notranslate"><span class="pre">ints</span></code> and <code class="docutils literal notranslate"><span class="pre">floats</span></code>, and format strings <code class="docutils literal notranslate"><span class="pre">i</span></code> and |
| <code class="docutils literal notranslate"><span class="pre">f</span></code> respectively.</p></li> |
| <li><p>A <code class="docutils literal notranslate"><span class="pre">map<string,</span> <span class="pre">float64></span></code> array has format string <code class="docutils literal notranslate"><span class="pre">+m</span></code>; its single child |
| has name <code class="docutils literal notranslate"><span class="pre">entries</span></code> and format string <code class="docutils literal notranslate"><span class="pre">+s</span></code>; its two grandchildren have names |
| <code class="docutils literal notranslate"><span class="pre">key</span></code> and <code class="docutils literal notranslate"><span class="pre">value</span></code>, and format strings <code class="docutils literal notranslate"><span class="pre">u</span></code> and <code class="docutils literal notranslate"><span class="pre">g</span></code> respectively.</p></li> |
| <li><p>A <code class="docutils literal notranslate"><span class="pre">sparse_union<ints:</span> <span class="pre">int32,</span> <span class="pre">floats:</span> <span class="pre">float32></span></code> with type ids <code class="docutils literal notranslate"><span class="pre">4,</span> <span class="pre">5</span></code> |
| has format string <code class="docutils literal notranslate"><span class="pre">+us:4,5</span></code>; its two children have names <code class="docutils literal notranslate"><span class="pre">ints</span></code> and |
| <code class="docutils literal notranslate"><span class="pre">floats</span></code>, and format strings <code class="docutils literal notranslate"><span class="pre">i</span></code> and <code class="docutils literal notranslate"><span class="pre">f</span></code> respectively.</p></li> |
| </ul> |
| </div> |
| </div> |
| <div class="section" id="structure-definitions"> |
| <h2>Structure definitions<a class="headerlink" href="#structure-definitions" title="Permalink to this headline">¶</a></h2> |
| <p>The following free-standing definitions are enough to support the Arrow |
| C data interface in your project. Like the rest of the Arrow project, they |
| are available under the Apache License 2.0.</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#define ARROW_FLAG_DICTIONARY_ORDERED 1</span> |
| <span class="cp">#define ARROW_FLAG_NULLABLE 2</span> |
| <span class="cp">#define ARROW_FLAG_MAP_KEYS_SORTED 4</span> |
| |
| <span class="k">struct</span> <span class="n">ArrowSchema</span> <span class="p">{</span> |
| <span class="c1">// Array type description</span> |
| <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">format</span><span class="p">;</span> |
| <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">;</span> |
| <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">metadata</span><span class="p">;</span> |
| <span class="kt">int64_t</span> <span class="n">flags</span><span class="p">;</span> |
| <span class="kt">int64_t</span> <span class="n">n_children</span><span class="p">;</span> |
| <span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">**</span> <span class="n">children</span><span class="p">;</span> |
| <span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">dictionary</span><span class="p">;</span> |
| |
| <span class="c1">// Release callback</span> |
| <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">release</span><span class="p">)(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span><span class="p">);</span> |
| <span class="c1">// Opaque producer-specific data</span> |
| <span class="kt">void</span><span class="o">*</span> <span class="n">private_data</span><span class="p">;</span> |
| <span class="p">};</span> |
| |
| <span class="k">struct</span> <span class="n">ArrowArray</span> <span class="p">{</span> |
| <span class="c1">// Array data description</span> |
| <span class="kt">int64_t</span> <span class="n">length</span><span class="p">;</span> |
| <span class="kt">int64_t</span> <span class="n">null_count</span><span class="p">;</span> |
| <span class="kt">int64_t</span> <span class="n">offset</span><span class="p">;</span> |
| <span class="kt">int64_t</span> <span class="n">n_buffers</span><span class="p">;</span> |
| <span class="kt">int64_t</span> <span class="n">n_children</span><span class="p">;</span> |
| <span class="k">const</span> <span class="kt">void</span><span class="o">**</span> <span class="n">buffers</span><span class="p">;</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">**</span> <span class="n">children</span><span class="p">;</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">dictionary</span><span class="p">;</span> |
| |
| <span class="c1">// Release callback</span> |
| <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">release</span><span class="p">)(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span><span class="p">);</span> |
| <span class="c1">// Opaque producer-specific data</span> |
| <span class="kt">void</span><span class="o">*</span> <span class="n">private_data</span><span class="p">;</span> |
| <span class="p">};</span> |
| </pre></div> |
| </div> |
| <div class="section" id="the-arrowschema-structure"> |
| <h3>The ArrowSchema structure<a class="headerlink" href="#the-arrowschema-structure" title="Permalink to this headline">¶</a></h3> |
| <p>The <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> structure describes the type and metadata of an exported |
| array or record batch. It has the following fields:</p> |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.format"> |
| <em class="property">const</em> char *<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">format</code><a class="headerlink" href="#c.ArrowSchema.format" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. A null-terminated, UTF8-encoded string describing |
| the data type. If the data type is nested, child types are not |
| encoded here but in the <a class="reference internal" href="#c.ArrowSchema.children" title="ArrowSchema.children"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.children</span></code></a> structures.</p> |
| <p>Consumers MAY decide not to support all data types, but they |
| should document this limitation.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.name"> |
| <em class="property">const</em> char *<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">name</code><a class="headerlink" href="#c.ArrowSchema.name" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A null-terminated, UTF8-encoded string of the field |
| or array name. This is mainly used to reconstruct child fields |
| of nested types.</p> |
| <p>Producers MAY decide not to provide this information, and consumers |
| MAY decide to ignore it. If omitted, MAY be NULL or an empty string.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.metadata"> |
| <em class="property">const</em> char *<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">metadata</code><a class="headerlink" href="#c.ArrowSchema.metadata" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A binary string describing the type’s metadata. |
| If the data type is nested, child types are not encoded here but |
| in the <a class="reference internal" href="#c.ArrowSchema.children" title="ArrowSchema.children"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.children</span></code></a> structures.</p> |
| <p>This string is not null-terminated but follows a specific format:</p> |
| <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">int32</span><span class="p">:</span> <span class="n">number</span> <span class="n">of</span> <span class="n">key</span><span class="o">/</span><span class="n">value</span> <span class="n">pairs</span> <span class="p">(</span><span class="n">noted</span> <span class="n">N</span> <span class="n">below</span><span class="p">)</span> |
| <span class="n">int32</span><span class="p">:</span> <span class="n">byte</span> <span class="n">length</span> <span class="n">of</span> <span class="n">key</span> <span class="mi">0</span> |
| <span class="n">key</span> <span class="mi">0</span> <span class="p">(</span><span class="ow">not</span> <span class="n">null</span><span class="o">-</span><span class="n">terminated</span><span class="p">)</span> |
| <span class="n">int32</span><span class="p">:</span> <span class="n">byte</span> <span class="n">length</span> <span class="n">of</span> <span class="n">value</span> <span class="mi">0</span> |
| <span class="n">value</span> <span class="mi">0</span> <span class="p">(</span><span class="ow">not</span> <span class="n">null</span><span class="o">-</span><span class="n">terminated</span><span class="p">)</span> |
| <span class="o">...</span> |
| <span class="n">int32</span><span class="p">:</span> <span class="n">byte</span> <span class="n">length</span> <span class="n">of</span> <span class="n">key</span> <span class="n">N</span> <span class="o">-</span> <span class="mi">1</span> |
| <span class="n">key</span> <span class="n">N</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">(</span><span class="ow">not</span> <span class="n">null</span><span class="o">-</span><span class="n">terminated</span><span class="p">)</span> |
| <span class="n">int32</span><span class="p">:</span> <span class="n">byte</span> <span class="n">length</span> <span class="n">of</span> <span class="n">value</span> <span class="n">N</span> <span class="o">-</span> <span class="mi">1</span> |
| <span class="n">value</span> <span class="n">N</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">(</span><span class="ow">not</span> <span class="n">null</span><span class="o">-</span><span class="n">terminated</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| <p>Integers are stored in native endianness. For example, the metadata |
| <code class="docutils literal notranslate"><span class="pre">[('key1',</span> <span class="pre">'value1')]</span></code> is encoded on a little-endian machine as:</p> |
| <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">x01</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x04</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x00key1</span>\<span class="n">x06</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x00value1</span> |
| </pre></div> |
| </div> |
| <p>On a big-endian machine, the same example would be encoded as:</p> |
| <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x01</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x04key1</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x00</span>\<span class="n">x06value1</span> |
| </pre></div> |
| </div> |
| <p>If omitted, this field MUST be NULL (not an empty string).</p> |
| <p>Consumers MAY choose to ignore this information.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.flags"> |
| int64_t <code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">flags</code><a class="headerlink" href="#c.ArrowSchema.flags" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A bitfield of flags enriching the type description. |
| Its value is computed by OR’ing together the flag values. |
| The following flags are available:</p> |
| <ul class="simple"> |
| <li><p><code class="docutils literal notranslate"><span class="pre">ARROW_FLAG_NULLABLE</span></code>: whether this field is semantically nullable |
| (regardless of whether it actually has null values).</p></li> |
| <li><p><code class="docutils literal notranslate"><span class="pre">ARROW_FLAG_DICTIONARY_ORDERED</span></code>: for dictionary-encoded types, |
| whether the ordering of dictionary indices is semantically meaningful.</p></li> |
| <li><p><code class="docutils literal notranslate"><span class="pre">ARROW_FLAG_MAP_KEYS_SORTED</span></code>: for map types, whether the keys within |
| each map value are sorted.</p></li> |
| </ul> |
| <p>If omitted, MUST be 0.</p> |
| <p>Consumers MAY choose to ignore some or all of the flags. Even then, |
| they SHOULD keep this value around so as to propagate its information |
| to their own consumers.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.n_children"> |
| int64_t <code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">n_children</code><a class="headerlink" href="#c.ArrowSchema.n_children" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. The number of children this type has.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.children"> |
| ArrowSchema **<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">children</code><a class="headerlink" href="#c.ArrowSchema.children" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A C array of pointers to each child type of this type. |
| There must be <a class="reference internal" href="#c.ArrowSchema.n_children" title="ArrowSchema.n_children"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.n_children</span></code></a> pointers.</p> |
| <p>MAY be NULL only if <a class="reference internal" href="#c.ArrowSchema.n_children" title="ArrowSchema.n_children"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.n_children</span></code></a> is 0.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.dictionary"> |
| ArrowSchema *<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">dictionary</code><a class="headerlink" href="#c.ArrowSchema.dictionary" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A pointer to the type of dictionary values.</p> |
| <p>MUST be present if the ArrowSchema represents a dictionary-encoded type. |
| MUST be NULL otherwise.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.release"> |
| void (*<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">release</code>)<span class="sig-paren">(</span><em class="property">struct</em> ArrowSchema*<span class="sig-paren">)</span><a class="headerlink" href="#c.ArrowSchema.release" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. A pointer to a producer-provided release callback.</p> |
| <p>See below for memory management and release callback semantics.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowSchema.private_data"> |
| void *<code class="sig-prename descclassname">ArrowSchema<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">private_data</code><a class="headerlink" href="#c.ArrowSchema.private_data" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. An opaque pointer to producer-provided private data.</p> |
| <p>Consumers MUST not process this member. Lifetime of this member |
| is handled by the producer, and especially by the release callback.</p> |
| </dd></dl> |
| |
| </div> |
| <div class="section" id="the-arrowarray-structure"> |
| <h3>The ArrowArray structure<a class="headerlink" href="#the-arrowarray-structure" title="Permalink to this headline">¶</a></h3> |
| <p>The <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> describes the data of an exported array or record batch. |
| For the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure to be interpreted type, the array type |
| or record batch schema must already be known. This is either done by |
| convention – for example a producer API that always produces the same data |
| type – or by passing a <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> on the side.</p> |
| <p>It has the following fields:</p> |
| <dl class="c member"> |
| <dt id="c.ArrowArray.length"> |
| int64_t <code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">length</code><a class="headerlink" href="#c.ArrowArray.length" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. The logical length of the array (i.e. its number of items).</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.null_count"> |
| int64_t <code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">null_count</code><a class="headerlink" href="#c.ArrowArray.null_count" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. The number of null items in the array. MAY be -1 if not |
| yet computed.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.offset"> |
| int64_t <code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">offset</code><a class="headerlink" href="#c.ArrowArray.offset" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. The logical offset inside the array (i.e. the number of items |
| from the physical start of the buffers). MUST be 0 or positive.</p> |
| <p>Producers MAY specify that they will only produce 0-offset arrays to |
| ease implementation of consumer code. |
| Consumers MAY decide not to support non-0-offset arrays, but they |
| should document this limitation.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.n_buffers"> |
| int64_t <code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">n_buffers</code><a class="headerlink" href="#c.ArrowArray.n_buffers" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. The number of physical buffers backing this array. The |
| number of buffers is a function of the data type, as described in the |
| <a class="reference internal" href="Columnar.html#format-columnar"><span class="std std-ref">Columnar format specification</span></a>.</p> |
| <p>Buffers of children arrays are not included.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.buffers"> |
| <em class="property">const</em> void **<code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">buffers</code><a class="headerlink" href="#c.ArrowArray.buffers" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. A C array of pointers to the start of each physical buffer |
| backing this array. Each <cite>void*</cite> pointer is the physical start of |
| a contiguous buffer. There must be <a class="reference internal" href="#c.ArrowArray.n_buffers" title="ArrowArray.n_buffers"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowArray.n_buffers</span></code></a> pointers.</p> |
| <p>The producer MUST ensure that each contiguous buffer is large enough to |
| represent <cite>length + offset</cite> values encoded according to the |
| <a class="reference internal" href="Columnar.html#format-columnar"><span class="std std-ref">Columnar format specification</span></a>.</p> |
| <p>It is recommended, but not required, that the memory addresses of the |
| buffers be aligned at least according to the type of primitive data that |
| they contain. Consumers MAY decide not to support unaligned memory.</p> |
| <p>The pointer to the null bitmap buffer, if the data type specifies one, |
| MAY be NULL only if <a class="reference internal" href="#c.ArrowArray.null_count" title="ArrowArray.null_count"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowArray.null_count</span></code></a> is 0.</p> |
| <p>Buffers of children arrays are not included.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.n_children"> |
| int64_t <code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">n_children</code><a class="headerlink" href="#c.ArrowArray.n_children" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. The number of children this array has. The number of children |
| is a function of the data type, as described in the |
| <a class="reference internal" href="Columnar.html#format-columnar"><span class="std std-ref">Columnar format specification</span></a>.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.children"> |
| ArrowArray **<code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">children</code><a class="headerlink" href="#c.ArrowArray.children" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A C array of pointers to each child array of this array. |
| There must be <a class="reference internal" href="#c.ArrowArray.n_children" title="ArrowArray.n_children"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowArray.n_children</span></code></a> pointers.</p> |
| <p>MAY be NULL only if <a class="reference internal" href="#c.ArrowArray.n_children" title="ArrowArray.n_children"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowArray.n_children</span></code></a> is 0.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.dictionary"> |
| ArrowArray *<code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">dictionary</code><a class="headerlink" href="#c.ArrowArray.dictionary" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. A pointer to the underlying array of dictionary values.</p> |
| <p>MUST be present if the ArrowArray represents a dictionary-encoded array. |
| MUST be NULL otherwise.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.release"> |
| void (*<code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">release</code>)<span class="sig-paren">(</span><em class="property">struct</em> ArrowArray*<span class="sig-paren">)</span><a class="headerlink" href="#c.ArrowArray.release" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Mandatory. A pointer to a producer-provided release callback.</p> |
| <p>See below for memory management and release callback semantics.</p> |
| </dd></dl> |
| |
| <dl class="c member"> |
| <dt id="c.ArrowArray.private_data"> |
| void *<code class="sig-prename descclassname">ArrowArray<code class="sig-prename descclassname">.</code></code><code class="sig-name descname">private_data</code><a class="headerlink" href="#c.ArrowArray.private_data" title="Permalink to this definition">¶</a><br /></dt> |
| <dd><p>Optional. An opaque pointer to producer-provided private data.</p> |
| <p>Consumers MUST not process this member. Lifetime of this member |
| is handled by the producer, and especially by the release callback.</p> |
| </dd></dl> |
| |
| </div> |
| <div class="section" id="dictionary-encoded-arrays"> |
| <h3>Dictionary-encoded arrays<a class="headerlink" href="#dictionary-encoded-arrays" title="Permalink to this headline">¶</a></h3> |
| <p>For dictionary-encoded arrays, the <a class="reference internal" href="#c.ArrowSchema.format" title="ArrowSchema.format"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.format</span></code></a> string |
| encodes the <em>index</em> type. The dictionary <em>value</em> type can be read |
| from the <a class="reference internal" href="#c.ArrowSchema.dictionary" title="ArrowSchema.dictionary"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.dictionary</span></code></a> structure.</p> |
| <p>The same holds for <code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure: while the parent |
| structure points to the index data, the <a class="reference internal" href="#c.ArrowArray.dictionary" title="ArrowArray.dictionary"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowArray.dictionary</span></code></a> |
| points to the dictionary values array.</p> |
| </div> |
| <div class="section" id="extension-arrays"> |
| <h3>Extension arrays<a class="headerlink" href="#extension-arrays" title="Permalink to this headline">¶</a></h3> |
| <p>For extension arrays, the <a class="reference internal" href="#c.ArrowSchema.format" title="ArrowSchema.format"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.format</span></code></a> string encodes the |
| <em>storage</em> type. Information about the extension type is encoded in the |
| <a class="reference internal" href="#c.ArrowSchema.metadata" title="ArrowSchema.metadata"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.metadata</span></code></a> string, similarly to the |
| <a class="reference internal" href="Columnar.html#format-metadata-extension-types"><span class="std std-ref">IPC format</span></a>. Specifically, the |
| metadata key <code class="docutils literal notranslate"><span class="pre">ARROW:extension:name</span></code> encodes the extension type name, |
| and the metadata key <code class="docutils literal notranslate"><span class="pre">ARROW:extension:metadata</span></code> encodes the |
| implementation-specific serialization of the extension type (for |
| parameterized extension types). The base64 encoding of metadata values |
| ensures that any possible serialization is representable.</p> |
| <p>The <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure exported from an extension array simply points |
| to the storage data of the extension array.</p> |
| </div> |
| <div class="section" id="memory-management"> |
| <h3>Memory management<a class="headerlink" href="#memory-management" title="Permalink to this headline">¶</a></h3> |
| <p>The <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structures follow the same conventions |
| for memory management. The term <em>“base structure”</em> below refers to the |
| <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> or <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> that is passed between producer and consumer |
| – not any child structure thereof.</p> |
| <div class="section" id="member-allocation"> |
| <h4>Member allocation<a class="headerlink" href="#member-allocation" title="Permalink to this headline">¶</a></h4> |
| <p>It is intended for the base structure to be stack- or heap-allocated by the |
| consumer. In this case, the producer API should take a pointer to the |
| consumer-allocated structure.</p> |
| <p>However, any data pointed to by the struct MUST be allocated and maintained |
| by the producer. This includes the format and metadata strings, the arrays |
| of buffer and children pointers, etc.</p> |
| <p>Therefore, the consumer MUST not try to interfere with the producer’s |
| handling of these members’ lifetime. The only way the consumer influences |
| data lifetime is by calling the base structure’s <code class="docutils literal notranslate"><span class="pre">release</span></code> callback.</p> |
| </div> |
| <div class="section" id="released-structure"> |
| <span id="c-data-interface-released"></span><h4>Released structure<a class="headerlink" href="#released-structure" title="Permalink to this headline">¶</a></h4> |
| <p>A released structure is indicated by setting its <code class="docutils literal notranslate"><span class="pre">release</span></code> callback to NULL. |
| Before reading and interpreting a structure’s data, consumers SHOULD check |
| for a NULL release callback and treat it accordingly (probably by erroring |
| out).</p> |
| </div> |
| <div class="section" id="release-callback-semantics-for-consumers"> |
| <h4>Release callback semantics – for consumers<a class="headerlink" href="#release-callback-semantics-for-consumers" title="Permalink to this headline">¶</a></h4> |
| <p>Consumers MUST call a base structure’s release callback when they won’t be using |
| it anymore, but they MUST not call any of its children’s release callbacks |
| (including the optional dictionary). The producer is responsible for releasing |
| the children.</p> |
| <p>In any case, a consumer MUST not try to access the base structure anymore |
| after calling its release callback – including any associated data such |
| as its children.</p> |
| </div> |
| <div class="section" id="release-callback-semantics-for-producers"> |
| <h4>Release callback semantics – for producers<a class="headerlink" href="#release-callback-semantics-for-producers" title="Permalink to this headline">¶</a></h4> |
| <p>If producers need additional information for lifetime handling (for |
| example, a C++ producer may want to use <code class="docutils literal notranslate"><span class="pre">shared_ptr</span></code> for array and |
| buffer lifetime), they MUST use the <code class="docutils literal notranslate"><span class="pre">private_data</span></code> member to locate the |
| required bookkeeping information.</p> |
| <p>The release callback MUST not assume that the structure will be located |
| at the same memory location as when it was originally produced. The consumer |
| is free to move the structure around (see “Moving an array”).</p> |
| <p>The release callback MUST walk all children structures (including the optional |
| dictionary) and call their own release callbacks.</p> |
| <p>The release callback MUST free any data area directly owned by the structure |
| (such as the buffers and children members).</p> |
| <p>The release callback MUST mark the structure as released, by setting |
| its <code class="docutils literal notranslate"><span class="pre">release</span></code> member to NULL.</p> |
| <p>Below is a good starting point for implementing a release callback, where the |
| TODO area must be filled with producer-specific deallocation code:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="kt">void</span> <span class="nf">ReleaseExportedArray</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// This should not be called on already released array</span> |
| <span class="n">assert</span><span class="p">(</span><span class="n">array</span><span class="o">-></span><span class="n">format</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span> |
| |
| <span class="c1">// Release children</span> |
| <span class="k">for</span> <span class="p">(</span><span class="kt">int64_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">array</span><span class="o">-></span><span class="n">n_children</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">child</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> |
| <span class="k">if</span> <span class="p">(</span><span class="n">child</span><span class="o">-></span><span class="n">release</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">release</span><span class="p">(</span><span class="n">child</span><span class="p">);</span> |
| <span class="n">assert</span><span class="p">(</span><span class="n">child</span><span class="o">-></span><span class="n">release</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">);</span> |
| <span class="p">}</span> |
| <span class="p">}</span> |
| |
| <span class="c1">// Release dictionary</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">dict</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">dictionary</span><span class="p">;</span> |
| <span class="k">if</span> <span class="p">(</span><span class="n">dict</span> <span class="o">!=</span> <span class="nb">NULL</span> <span class="o">&&</span> <span class="n">dict</span><span class="o">-></span><span class="n">release</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> |
| <span class="n">dict</span><span class="o">-></span><span class="n">release</span><span class="p">(</span><span class="n">dict</span><span class="p">);</span> |
| <span class="n">assert</span><span class="p">(</span><span class="n">dict</span><span class="o">-></span><span class="n">release</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">);</span> |
| <span class="p">}</span> |
| |
| <span class="c1">// TODO here: release and/or deallocate all data directly owned by</span> |
| <span class="c1">// the ArrowArray struct, such as the private_data.</span> |
| |
| <span class="c1">// Mark array released</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">release</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| </div> |
| <div class="section" id="moving-an-array"> |
| <h4>Moving an array<a class="headerlink" href="#moving-an-array" title="Permalink to this headline">¶</a></h4> |
| <p>The consumer can <em>move</em> the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure by bitwise copying or |
| shallow member-wise copying. Then it MUST mark the source structure released |
| (see “released structure” above for how to do it) but <em>without</em> calling the |
| release callback. This ensures that only one live copy of the struct is |
| active at any given time and that lifetime is correctly communicated to |
| the producer.</p> |
| <p>As usual, the release callback will be called on the destination structure |
| when it is not needed anymore.</p> |
| <div class="section" id="moving-child-arrays"> |
| <h5>Moving child arrays<a class="headerlink" href="#moving-child-arrays" title="Permalink to this headline">¶</a></h5> |
| <p>It is also possible to move one or several child arrays, but the parent |
| <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure MUST be released immediately afterwards, as it |
| won’t point to valid child arrays anymore.</p> |
| <p>The main use case for this is to keep alive only a subset of child arrays |
| (for example if you are only interested in certain columns of the data), |
| while releasing the others.</p> |
| <div class="admonition note"> |
| <p class="admonition-title">Note</p> |
| <p>For moving to work correctly, the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure has to be |
| trivially relocatable. Therefore, pointer members inside the <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> |
| structure (including <code class="docutils literal notranslate"><span class="pre">private_data</span></code>) MUST not point inside the structure |
| itself. Also, external pointers to the structure MUST not be separately |
| stored by the producer. Instead, the producer MUST use the <code class="docutils literal notranslate"><span class="pre">private_data</span></code> |
| member so as to remember any necessary bookkeeping information.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="section" id="record-batches"> |
| <h3>Record batches<a class="headerlink" href="#record-batches" title="Permalink to this headline">¶</a></h3> |
| <p>A record batch can be trivially considered as an equivalent struct array with |
| additional top-level metadata.</p> |
| </div> |
| </div> |
| <div class="section" id="example-use-case"> |
| <h2>Example use case<a class="headerlink" href="#example-use-case" title="Permalink to this headline">¶</a></h2> |
| <p>A C++ database engine wants to provide the option to deliver results in Arrow |
| format, but without imposing themselves a dependency on the Arrow software |
| libraries. With the Arrow C data interface, the engine can let the caller pass |
| a pointer to a <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure, and fill it with the next chunk of |
| results.</p> |
| <p>It can do so without including the Arrow C++ headers or linking with the |
| Arrow DLLs. Furthermore, the database engine’s C API can benefit other |
| runtimes and libraries that know about the Arrow C data interface, |
| through e.g. a C FFI layer.</p> |
| </div> |
| <div class="section" id="c-producer-examples"> |
| <h2>C producer examples<a class="headerlink" href="#c-producer-examples" title="Permalink to this headline">¶</a></h2> |
| <div class="section" id="exporting-a-simple-int32-array"> |
| <h3>Exporting a simple <code class="docutils literal notranslate"><span class="pre">int32</span></code> array<a class="headerlink" href="#exporting-a-simple-int32-array" title="Permalink to this headline">¶</a></h3> |
| <p>Export a non-nullable <code class="docutils literal notranslate"><span class="pre">int32</span></code> type with empty metadata. In this case, |
| all <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> members point to statically-allocated data, so the |
| release callback is trivial.</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="kt">void</span> <span class="nf">release_int32_type</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">schema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Mark released</span> |
| <span class="n">schema</span><span class="o">-></span><span class="n">release</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> |
| <span class="p">}</span> |
| |
| <span class="kt">void</span> <span class="nf">export_int32_type</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">schema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="o">*</span><span class="n">schema</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Type description</span> |
| <span class="p">.</span><span class="n">format</span> <span class="o">=</span> <span class="s">"i"</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">""</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">children</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_int32_type</span> |
| <span class="p">};</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| <p>Export a C-malloc()ed array of the same type as a Arrow array, transferring |
| ownership to the consumer through the release callback:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="kt">void</span> <span class="nf">release_int32_array</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span> |
| <span class="n">assert</span><span class="p">(</span><span class="n">array</span><span class="o">-></span><span class="n">n_buffers</span> <span class="o">==</span> <span class="mi">2</span><span class="p">);</span> |
| <span class="c1">// Free the buffers and the buffers array</span> |
| <span class="n">free</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span> <span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> |
| <span class="n">free</span><span class="p">(</span><span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">);</span> |
| <span class="c1">// Mark released</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">release</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> |
| <span class="p">}</span> |
| |
| <span class="kt">void</span> <span class="nf">export_int32_array</span><span class="p">(</span><span class="k">const</span> <span class="kt">int32_t</span><span class="o">*</span> <span class="n">data</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">nitems</span><span class="p">,</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Initialize primitive fields</span> |
| <span class="o">*</span><span class="n">array</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Data description</span> |
| <span class="p">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">nitems</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">null_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_buffers</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">children</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_int32_array</span> |
| <span class="p">};</span> |
| <span class="c1">// Allocate list of buffers</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">buffers</span> <span class="o">=</span> <span class="p">(</span><span class="k">const</span> <span class="kt">void</span><span class="o">**</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span> <span class="o">*</span> <span class="n">array</span><span class="o">-></span><span class="n">n_buffers</span><span class="p">);</span> |
| <span class="n">assert</span><span class="p">(</span><span class="n">array</span><span class="o">-></span><span class="n">buffers</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// no nulls, null bitmap can be omitted</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| </div> |
| <div class="section" id="exporting-a-struct-float32-utf8-array"> |
| <h3>Exporting a <code class="docutils literal notranslate"><span class="pre">struct<float32,</span> <span class="pre">utf8></span></code> array<a class="headerlink" href="#exporting-a-struct-float32-utf8-array" title="Permalink to this headline">¶</a></h3> |
| <p>Export the array type as a <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> with C-malloc()ed children:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="kt">void</span> <span class="nf">release_malloced_type</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">schema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> |
| <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">schema</span><span class="o">-></span><span class="n">n_children</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> |
| <span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">child</span> <span class="o">=</span> <span class="n">schema</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> |
| <span class="k">if</span> <span class="p">(</span><span class="n">child</span><span class="o">-></span><span class="n">release</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">release</span><span class="p">(</span><span class="n">child</span><span class="p">);</span> |
| <span class="p">}</span> |
| <span class="p">}</span> |
| <span class="n">free</span><span class="p">(</span><span class="n">schema</span><span class="o">-></span><span class="n">children</span><span class="p">);</span> |
| <span class="c1">// Mark released</span> |
| <span class="n">schema</span><span class="o">-></span><span class="n">release</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> |
| <span class="p">}</span> |
| |
| <span class="kt">void</span> <span class="nf">export_float32_utf8_type</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">schema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span> <span class="n">child</span><span class="p">;</span> |
| |
| <span class="c1">//</span> |
| <span class="c1">// Initialize parent type</span> |
| <span class="c1">//</span> |
| <span class="o">*</span><span class="n">schema</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Type description</span> |
| <span class="p">.</span><span class="n">format</span> <span class="o">=</span> <span class="s">"+s"</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">""</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_malloced_type</span> |
| <span class="p">};</span> |
| <span class="c1">// Allocate list of children types</span> |
| <span class="n">schema</span><span class="o">-></span><span class="n">children</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="o">*</span><span class="p">)</span> <span class="o">*</span> <span class="n">schema</span><span class="o">-></span><span class="n">n_children</span><span class="p">);</span> |
| |
| <span class="c1">//</span> |
| <span class="c1">// Initialize child type #0</span> |
| <span class="c1">//</span> |
| <span class="n">child</span> <span class="o">=</span> <span class="n">schema</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="p">));</span> |
| <span class="o">*</span><span class="n">child</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Type description</span> |
| <span class="p">.</span><span class="n">format</span> <span class="o">=</span> <span class="s">"f"</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"floats"</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">ARROW_FLAG_NULLABLE</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">children</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_malloced_type</span> |
| <span class="p">};</span> |
| |
| <span class="c1">//</span> |
| <span class="c1">// Initialize child type #1</span> |
| <span class="c1">//</span> |
| <span class="n">child</span> <span class="o">=</span> <span class="n">schema</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="p">));</span> |
| <span class="o">*</span><span class="n">child</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowSchema</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Type description</span> |
| <span class="p">.</span><span class="n">format</span> <span class="o">=</span> <span class="s">"u"</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"strings"</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">flags</span> <span class="o">=</span> <span class="n">ARROW_FLAG_NULLABLE</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">children</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_malloced_type</span> |
| <span class="p">};</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| <p>Export C-malloc()ed arrays in Arrow-compatible layout as an Arrow struct array, |
| transferring ownership to the consumer:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="kt">void</span> <span class="nf">release_malloced_array</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span> |
| <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> |
| <span class="c1">// Free children</span> |
| <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">array</span><span class="o">-></span><span class="n">n_children</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">child</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> |
| <span class="k">if</span> <span class="p">(</span><span class="n">child</span><span class="o">-></span><span class="n">release</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">release</span><span class="p">(</span><span class="n">child</span><span class="p">);</span> |
| <span class="p">}</span> |
| <span class="p">}</span> |
| <span class="n">free</span><span class="p">(</span><span class="n">array</span><span class="o">-></span><span class="n">children</span><span class="p">);</span> |
| <span class="c1">// Free buffers</span> |
| <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">array</span><span class="o">-></span><span class="n">n_buffers</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> |
| <span class="n">free</span><span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span> <span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> |
| <span class="p">}</span> |
| <span class="n">free</span><span class="p">(</span><span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">);</span> |
| <span class="c1">// Mark released</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">release</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> |
| <span class="p">}</span> |
| |
| <span class="kt">void</span> <span class="nf">export_float32_utf8_array</span><span class="p">(</span> |
| <span class="kt">int64_t</span> <span class="n">nitems</span><span class="p">,</span> |
| <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">float32_nulls</span><span class="p">,</span> <span class="k">const</span> <span class="kt">float</span><span class="o">*</span> <span class="n">float32_data</span><span class="p">,</span> |
| <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">utf8_nulls</span><span class="p">,</span> <span class="k">const</span> <span class="kt">int32_t</span><span class="o">*</span> <span class="n">utf8_offsets</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">utf8_data</span><span class="p">,</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span> |
| <span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span> <span class="n">child</span><span class="p">;</span> |
| |
| <span class="c1">//</span> |
| <span class="c1">// Initialize parent array</span> |
| <span class="c1">//</span> |
| <span class="o">*</span><span class="n">array</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Data description</span> |
| <span class="p">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">nitems</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">null_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_buffers</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_malloced_array</span> |
| <span class="p">};</span> |
| <span class="c1">// Allocate list of parent buffers</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">buffers</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span> <span class="o">*</span> <span class="n">array</span><span class="o">-></span><span class="n">n_buffers</span><span class="p">);</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// no nulls, null bitmap can be omitted</span> |
| <span class="c1">// Allocate list of children arrays</span> |
| <span class="n">array</span><span class="o">-></span><span class="n">children</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="o">*</span><span class="p">)</span> <span class="o">*</span> <span class="n">array</span><span class="o">-></span><span class="n">n_children</span><span class="p">);</span> |
| |
| <span class="c1">//</span> |
| <span class="c1">// Initialize child array #0</span> |
| <span class="c1">//</span> |
| <span class="n">child</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="p">));</span> |
| <span class="o">*</span><span class="n">child</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Data description</span> |
| <span class="p">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">nitems</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">null_count</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_buffers</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">children</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_malloced_array</span> |
| <span class="p">};</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span> <span class="o">*</span> <span class="n">array</span><span class="o">-></span><span class="n">n_buffers</span><span class="p">);</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">float32_nulls</span><span class="p">;</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">float32_data</span><span class="p">;</span> |
| |
| <span class="c1">//</span> |
| <span class="c1">// Initialize child array #1</span> |
| <span class="c1">//</span> |
| <span class="n">child</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">children</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="p">));</span> |
| <span class="o">*</span><span class="n">child</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">ArrowArray</span><span class="p">)</span> <span class="p">{</span> |
| <span class="c1">// Data description</span> |
| <span class="p">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">nitems</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">null_count</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_buffers</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">n_children</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">dictionary</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="p">.</span><span class="n">children</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> |
| <span class="c1">// Bookkeeping</span> |
| <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="o">&</span><span class="n">release_malloced_array</span> |
| <span class="p">};</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span> <span class="o">*</span> <span class="n">array</span><span class="o">-></span><span class="n">n_buffers</span><span class="p">);</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">utf8_nulls</span><span class="p">;</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">utf8_offsets</span><span class="p">;</span> |
| <span class="n">child</span><span class="o">-></span><span class="n">buffers</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">utf8_data</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| </div> |
| </div> |
| <div class="section" id="why-two-distinct-structures"> |
| <h2>Why two distinct structures?<a class="headerlink" href="#why-two-distinct-structures" title="Permalink to this headline">¶</a></h2> |
| <p>In many cases, the same type or schema description applies to multiple, |
| possibly short, batches of data. To avoid paying the cost of exporting |
| and importing the type description for each batch, the <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> |
| can be passed once, separately, at the beginning of the conversation between |
| producer and consumer.</p> |
| <p>In other cases yet, the data type is fixed by the producer API, and may not |
| need to be communicated at all.</p> |
| <p>However, if a producer is focused on one-shot exchange of data, it can |
| communicate the <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structures in the same |
| API call.</p> |
| </div> |
| <div class="section" id="updating-this-specification"> |
| <h2>Updating this specification<a class="headerlink" href="#updating-this-specification" title="Permalink to this headline">¶</a></h2> |
| <p>Once this specification is supported in an official Arrow release, the C |
| ABI is frozen. This means the <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure |
| definitions should not change in any way – including adding new members.</p> |
| <p>Backwards-compatible changes are allowed, for example new |
| <a class="reference internal" href="#c.ArrowSchema.flags" title="ArrowSchema.flags"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.flags</span></code></a> values or expanded possibilities for |
| the <a class="reference internal" href="#c.ArrowSchema.format" title="ArrowSchema.format"><code class="xref c c-member docutils literal notranslate"><span class="pre">ArrowSchema.format</span></code></a> string.</p> |
| <p>Any incompatible changes should be part of a new specification, for example |
| “Arrow C data interface v2”.</p> |
| </div> |
| <div class="section" id="inspiration"> |
| <h2>Inspiration<a class="headerlink" href="#inspiration" title="Permalink to this headline">¶</a></h2> |
| <p>The Arrow C data interface is inspired by the <a class="reference external" href="https://www.python.org/dev/peps/pep-3118/">Python buffer protocol</a>, |
| which has proven immensely successful in allowing various Python libraries |
| exchange numerical data with no knowledge of each other and near-zero |
| adaptation cost.</p> |
| </div> |
| </div> |
| |
| |
| </div> |
| |
| </div> |
| <footer> |
| <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation"> |
| <a href="CStreamInterface.html" class="btn btn-neutral float-right" title="The Arrow C stream interface" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> |
| <a href="Integration.html" class="btn btn-neutral float-left" title="Integration Testing" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> |
| </div> |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <p> |
| © Copyright 2016-2019 Apache Software Foundation. |
| |
| </p> |
| </div> |
| |
| |
| |
| Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a |
| |
| <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> |
| |
| provided by <a href="https://readthedocs.org">Read the Docs</a>. |
| |
| </footer> |
| </div> |
| </div> |
| |
| </section> |
| |
| </div> |
| |
| |
| <script type="text/javascript"> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| |
| |
| |
| |
| |
| |
| <script type="text/javascript" src="/docs/_static/versionwarning.js"></script></body> |
| </html> |