.. _c_interface:

C Interface
===========

You can use the C interface of ATC by including the public header ``include/c/atc.h``, which includes all public header files (located in ``include/c/atc/``). Check out `this example <URL_REPOSITORY_TREE/examples/example.c>`_ for a demonstration.

There are several situations which warrant the use of the C interface:

* For a C application
* For an application in another language which supports interfacing with native functions, such as Python, Matlab, Julia or Fortran.
* For a C++ application that cannot guarantee ABI stability (see the :ref:`C++ Interface page <cpp_interface>` for more information).

Note that the C interface is simply a wrapper around the C++ interface and does not provide any extra functionality. However, due to the limitations of the C language and the need to provide an interface using only simple C types, the C interface is noticeably more verbose and complicated:

* STL containers are replaced by basic containers:

   * ``std::string`` is replaced by ``const char*``.
   * ``std::vector<T>`` is replaced by a a combination of the array length (``size_t``) and a pointer to the first element (``T*``).
   * ``std::map`` is replaced by a similar combination, this time pointing to an array of custom structs, each representing a tuple from the original ``std::map``.
   
* C does not support templates, so each C++ templated function is explicitly instantiated for each of its valid types (with different names).
* C does not support default arguments, so each function has two versions: one which takes in custom options and one which uses the default options.
* C does not support overloaded functions, so the overloads used in the C++ interface also need to be disambiguated using a naming scheme.
* C does not handle automatic destruction of heap-allocated objects like C++, so for convenience each function that returns an :any:`atc::Results` object in C++ has two versions:

   * A version that destroys the :any:`atc::Results` struct and only returns a ``bool`` value, indicating if the function executed successfully.
   * A version that wraps a C struct :any:`atc_results` around the :any:`atc::Results` struct using an opaque pointer and returns the :any:`atc_results` struct. Whether or not the function executed successfully is indicated in the field ``success`` of :any:`atc_results`. **When using functions that return** :any:`atc_results` **, the result should be stored and properly destroyed by explicitly passing it onto** :any:`atc_destroy_results` **to avoid memory leaks.**

* Dynamic memory management is cumbersome in C and therefore delegated to the user as much as possible. As a result, we do not provide an equivalent of decompressing to an ``std::vector<dtype>``. Instead, C users should always decompress to a pre-allocated array of the right type and size as determined by :ref:`c_atc_read_data_type` and :ref:`c_atc_read_decompressed_size`.
* C does not support exceptions, so instead the return value of each C function in our API contains a value that indicates whether or not the call succeeded. If a call fails, this is normally due to an ATC exception that was thrown by the C++ part of the library and caught by the wrapper.

Combining all this, the C interface of ATC consists of a very large amount of very similar functions. Because of this, and the fact that most aspects of this interface are straightforward wrappers around their :ref:`C++ counterparts <cpp_interface>`, we will not document this section as extensively. Instead, we will mainly focus on the differences from the C++ interface.

Furthermore, note that all C enums values have explicit integer values assigned to them in order to facilitate calls from other languages (e.g. Python), since the symbols representing these values are not present in the compiled binaries and thus cannot be used in such situations.

.. toctree::
   :maxdepth: 2
   :caption: Contents:
   
   c/interface
   c/options
   c/results
