# C library

`src/mscb.cxx` exposes a C-compatible interface through `include/mscb.h`.
Applications include the header, initialize a connection, operate on node
addresses and close the descriptor.

```c
#include "mscb.h"

int main(void)
{
    char device[256] = "192.0.2.40";
    int fd = mscb_init(device, sizeof(device), "", 0);
    if (fd < 0)
        return 1;

    if (mscb_ping(fd, 1, 0, 1) == MSCB_SUCCESS) {
        float value = 0;
        int size = sizeof(value);
        if (mscb_read(fd, 1, 0, &value, &size) == MSCB_SUCCESS) {
            /* use value; inspect variable metadata before assuming a type */
        }
    }

    mscb_exit(fd);
    return 0;
}
```

## Important conventions

- A non-negative descriptor returned by `mscb_init()` identifies a connection.
- Most operations return an `MSCB_*` status; initialization may return a
  negative `EMSCB_*` error.
- Read `MSCB_INFO_VAR` before interpreting raw value bytes. Width and flags
  determine representation.
- `size` in read APIs is both input capacity and output byte count.
- The library serializes access with a per-device lock. Do not retain internal
  descriptor-table pointers.
- `mscb_flash()` persists node settings and is slower than an ordinary write.

The complete function list is in the [C API reference](../reference/c-api.md),
with structures and result codes under [types and status](../reference/types-and-status.md).
C++ applications can instead use the higher-level
[MSCB++ API](../reference/mscbxx-api.md).

## Ethernet behavior

For an Ethernet descriptor, API operations become one or more version-5 UDP
exchanges with the submaster. Address cycles and command bytes are kept
separate so the submaster can create the RS-485 ninth bit. See
[Ethernet transport](../protocol/ethernet.md).
