# Iceoryx C Language binding

If you are looking for an example take a look at the
[icedelivery on c example](../iceoryx_examples/icedelivery_in_c).

## C API structure

The C API is supposed to be as close to the C++ API as possible. This means, developers who are
already familiar with the C++ API do not have to learn iceoryx from scratch in order to use the C API.
There are of course differences due to C being a different language than C++.

Therefore, we have the following coding conventions exclusively in the C API.

- C functions are using an abbreviation of the class name. For instance `Subscriber` would use `sub` and
  the methods are named like `iox_sub_method_name` where the `camelCase` is converted into `snake_case`.
- A typedef for the handle is created with the abbreviation as name, a `iox` prefix and a `_t` suffix,
  like `iox_sub_t`
- If the constructor allocates an element it has the suffix `_create` and is called for instance
  `iox_node_create`. Analog to the constructor the destructor has the suffix `_destroy` and is named
  like `iox_node_destroy`.
- Pre iceoryx v2, constructor requiring preallocated memory had the suffix `_init` and required a pointer
  to a storage which was usually placed on the stack. Due to non-trivial issues with different sizes for
  different platforms and architectures the storage is ignored and the object is allocated on the heap.
  This might be reverted in a future release depending on a proper solution for the problem.
  The API remains the same, so a `_storage_t` object like `iox_sub_storage_t` must be created and
  a pointer to this object must be passed to `_init`, e.g. `iox_sub_init`. This function returns a handle
  which does not point to the storage. Using the address of the storage in `_deinit` is undefined and
  most likely will result in a segmentation fault.
  The usage is according the following example

  ```c
  iox_sub_storage_t subStorage;
  iox_sub_t subscriber = iox_sub_init(&subStorage, "foo", "bar", "baz", nullptr);
  // do something with subscriber
  iox_sub_deinit(subscriber);
  ```

- The first parameter is always the handle to the corresponding object.
- If possible, the arguments should stay the same in the C API.

- Enum values are named like `EnumName_EnumValue`
- Enum names follow the rule `namespace_EnumName`

Here is an example:

```cpp
namespace iox {
enum class Color {
    RED,
    GREEN,
    BLUE
};

class Channel {
    public:
        Channel(const std::string &name);
        cxx::optional<void*> receive();
        bool send(void * data);
        void allHailHypnotoad();
};

class MyOtherClass {
    public:
        MyOtherClass(const int a);
        void youSpinMeRoundLikeARecord();
};
}
```

The corresponding C binding would then look like:

```c
enum iox_Color {
    Color_RED,
    Color_GREEN,
    Color_BLUE,
};


typedef struct Channel * sub_t;

sub_t iox_chan_create(const char * name);
void iox_chan_destroy(sub_t const self);
bool iox_chan_receive(sub_t const self, void * const data);
bool iox_chan_send(sub_t const self, void * const data);
void iox_chan_all_hail_hypnotoad(sub_t const self);


struct iox_other_class_storage_t_ {
    uint64_t do_not_touch_me[8]; // lets assume 8 * 8 is the size of MyOtherClass
};
typedef iox_other_class_storage_t_ iox_other_class_storage_t;

typedef struct MyOtherClass * iox_other_class_t;
iox_other_class_t iox_other_class_init(iox_other_class_storage_t * self,const int a);
void iox_other_class_deinit(iox_other_class_t * self);
void iox_other_class_you_spin_me_round_like_a_record(iox_other_class_t * self);
```
