> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wuji.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# C API Reference

Wuji SDK provides a C API (`libwuji_sdk_c.so` on Linux, `libwuji_sdk_c.dylib` on macOS, or `wuji_sdk_c.dll` on Windows, with `wuji_sdk.h` on all platforms) with the same semantics as the Python interface. For installation alongside Python, see [Installation and Environment](https://docs.wuji.tech/docs/en/wuji-sdk/latest/quick-start.md#installation).

This page covers the C-side initialization conventions, memory and callback constraints, error code decoding, and project build setup. Per-device C APIs live with each product's docs: [Wuji Hand 2 SDK Reference](https://docs.wuji.tech/docs/en/wuji-hand/latest/sdk-reference.md) and [Wuji Glove SDK and Data Reference](https://docs.wuji.tech/docs/en/wuji-glove/latest/sdk-data-reference/index.md). Cross-device capabilities live in the capability chapters, each with an operation / Python / C table: [Device Discovery & Connection](https://docs.wuji.tech/docs/en/wuji-sdk/latest/device-connection.md), [SDK Users and Calibration Data](https://docs.wuji.tech/docs/en/wuji-sdk/latest/device-params.md), [Data Subscription Mechanism](https://docs.wuji.tech/docs/en/wuji-sdk/latest/data-subscription.md), [Time Synchronization and Coordinate Transforms](https://docs.wuji.tech/docs/en/wuji-sdk/latest/time-sync.md), and [Hand Retargeting](https://docs.wuji.tech/docs/en/wuji-sdk/latest/retargeting.md).

The complete typed callback signatures and struct definitions live in `include/wuji_sdk.h` of the extracted tarball (download it from [wuji-sdk Releases](https://github.com/wuji-technology/wuji-sdk/releases)). The CMake example and build instructions are in the [`examples/c/` directory of the wuji-sdk repo](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/README.md).

For Wuji Glove offline computation, model queries, and output cleanup, see [Offline Solving](https://docs.wuji.tech/docs/en/wuji-glove/latest/offline-pipeline.md).

For C MCAP recording examples, monitoring, and cleanup, see [Data Recording](https://docs.wuji.tech/docs/en/wuji-sdk/latest/data-recording.md#c-recording).

## Initialization and conventions

**Initialization**

Call once at process start and release at shutdown:

```c theme={null}
#include "wuji_sdk.h"

if (wuji_init(NULL) != WUJI_STATUS_OK) {
    fprintf(stderr, "init failed: %s\n", wuji_last_error());
    return 1;
}

// ... your code

wuji_shutdown();
```

**Return value taxonomy**

* `WujiStatus` — most operations (`wuji_init` / `wuji_scan` / `wuji_connect` / opening subscriptions, etc.). `WUJI_STATUS_OK` means success. On failure, retrieve the per-thread error string via `wuji_last_error()`.
* `int32_t` — metadata readers (`wuji_dev_serial_number` / `wuji_dev_device_name`) return the number of bytes written.
* `uint8_t` — status query `wuji_dev_is_connected`.
* `void` — `wuji_shutdown` and resource cleanup functions.

**Resource cleanup functions**

* `wuji_discovered_free` — release the device list returned by `wuji_scan`
* `wuji_dev_release` — paired with `wuji_connect`, release the device handle after disconnecting
* `wuji_sub_close` — close the subscription handle

**User Info Struct**

`WujiUserInfo` holds seven fields: `user_id`, `display_name`, `description`, `external_id`, `is_default`, `created_at`, and `updated_at`. `wuji_update_user` takes a `WujiUserUpdate` carrying only the fields to change, and setting `clear_description` / `clear_external_id` clears the matching value. For the full user management API list, see [SDK Users and Calibration Data](https://docs.wuji.tech/docs/en/wuji-sdk/latest/device-params.md#sdk-user-management).

## Error Code Description

`wuji_describe_error(full_code, &info)` looks up full codes for Wuji Hand 2 or Wuji Glove. For an example and return codes, see [Fault Logs and Error Codes](https://docs.wuji.tech/docs/en/wuji-sdk/latest/device-fault-logs.md#look-up-error-codes).

`wuji_hand_2_describe_error(code, &info)` accepts native Wuji Hand 2 integer fault codes, such as `joint_diagnostics.error_code_current`, without a device connection. Encoder calibration's `enc1_error_code` and `enc2_error_code` and the Wuji Hand joint diagnostics `WujiHandJointDiagnostics.error_code` bitfield are different code types and must not be passed to this function. Example:

```c theme={null}
WujiErrorInfo info = {0};
// 0x2102 = Overcurrent (ImmediateStop / ManualClear), a real production fault code
if (wuji_hand_2_describe_error(0x2102, &info) == WUJI_STATUS_OK) {
    printf("name=%s severity=%s\ndesc=%s\ncause=%s\n",
           info.name, info.severity, info.desc, info.cause);
}
```

Unknown codes return `WUJI_STATUS_ERR_NOT_FOUND`.

## Usage constraints

C SDK users must observe the following constraints to avoid use-after-free, deadlocks, and reading stale error strings.

* A typed callback's `frame` pointer is valid only for the duration of the callback. Heap fields are released after the callback returns. Copy whatever you need to retain inside the callback. Do not store the pointer.
* Never call `wuji_sub_close` from inside that subscription's own callback. `close` joins the worker thread and will deadlock if called from the callback itself. Close from a different thread.
* The return value of `wuji_last_error()` is only valid until the next `wuji_*` call on the same thread. Copy the message immediately if you need to retain it.
* `END` and `ERROR` are terminal frames — no further data will arrive after them, but you still need to call `wuji_sub_close` to release the subscription handle.
* String getters use a two-call query: first call with `buf=NULL, buf_len=0` to read `*needed` (required bytes including NUL), then allocate and call again to fill. Passing an undersized buffer returns `WUJI_STATUS_ERR_BUFFER_TOO_SMALL` and never truncates.
* Whole-hand batch reads (`get_all_effort_limit` / `get_all_mit_params`) return a flat-20 array plus an online bitmap. Use the `WUJI_JOINT_ONLINE(mask, i)` macro to check slot validity, otherwise you will read offline-joint placeholders (0 or NaN).
* The calibration feedback callback runs on the calibration worker thread, and the `feedback` pointer is valid only during the callback. The SDK guards the session calls made from inside it rather than deadlocking: `wuji_glove_calibration_wait` and `wuji_glove_calibration_try_finish` return `WUJI_STATUS_ERR_INVALID_ARG`, and `wuji_glove_calibration_session_free` records the reason in `wuji_last_error()` and skips the release — so the session stays alive and you must free it again after the callback returns. `wuji_glove_calibration_cancel` is safe to call from the callback. Free the session with `wuji_glove_calibration_session_free` and the result with `wuji_glove_calibration_result_free`.
* `WujiUserInfo` holds heap strings: free a single struct with `wuji_user_info_free`, and free an array returned by `wuji_list_users` with `wuji_user_info_array_free`.

## Python equivalents

The table below maps each C API to its Python counterpart by capability. For full usage of the cross-device capabilities, see the capability chapters listed at the top of this page. For per-device APIs, see the product documentation listed at the top of this page.

<table>
  <thead>
    <tr><th>Capability</th><th>C</th><th>Python</th></tr>
  </thead>

  <tbody>
    <tr><td>Init</td><td>`wuji_init(NULL)`</td><td>`SdkManager.instance()`</td></tr>
    <tr><td>Scan</td><td>`wuji_scan(&devs, &count)`</td><td>`manager.scan()`</td></tr>
    <tr><td>Connect</td><td>`wuji_connect(&target, alias, &opts, &dev)`</td><td>`manager.connect(...)` / `manager.auto_connect(...)`</td></tr>
    <tr><td>Default connect options</td><td>`wuji_connect_options_default()`</td><td>`ConnectOptions()`</td></tr>
    <tr><td>Device subscribe</td><td>`wuji_glove_subscribe_tactile(dev, cb, user, &sub)`</td><td>`glove.tactile().subscribe_with_callback(...)`</td></tr>
    <tr><td>Global subscribe</td><td>`wuji_subscribe_tf(cb, user, &sub)`</td><td>`manager.tf().subscribe()`</td></tr>
    <tr><td>Stream output rate</td><td>`wuji_sub_set_rate(sub, hz, &actual)`</td><td>`sub.set_rate(hz)`</td></tr>
    <tr><td>Hand 2 control action</td><td>`wuji_hand_2_enable(dev, mask)`</td><td>`hand.enable(joints=mask)`</td></tr>
    <tr><td>Hand 2 Whole-Hand Control Mode</td><td>`wuji_hand_2_set_control_mode` / `wuji_hand_2_get_control_mode`</td><td>`hand.control_mode().set(...)` / `.get()`</td></tr>
    <tr><td>Hand 2 Position-Command Low-Pass Cutoff</td><td>`wuji_hand_2_set_position_command_low_pass_cutoff_frequency` / `wuji_hand_2_get_position_command_low_pass_cutoff_frequency`</td><td>`hand.position_command_low_pass_cutoff_frequency().set(hz)` / `.get()`</td></tr>
    <tr><td>Hand 2 realtime command</td><td>`wuji_hand_2_joint_command_publish` + `wuji_joint_command_publisher_send`</td><td>`hand.joint_command().publish().send([...])`</td></tr>
    <tr><td>Hand 2 joint state subscribe</td><td>`wuji_hand_2_subscribe_joint_states`</td><td>`hand.joint_states().subscribe()`</td></tr>
    <tr><td>Hand 2 joint diagnostics subscribe</td><td>`wuji_hand_2_subscribe_joint_diagnostics`</td><td>`hand.joint_diagnostics().subscribe()`</td></tr>
    <tr><td>Hand 2 IMU subscribe</td><td>`wuji_hand_2_subscribe_imu`</td><td>`hand.imu().subscribe()`</td></tr>
    <tr><td>Hand 2 error description</td><td>`wuji_hand_2_describe_error(code, &info)`</td><td>`WujiHand2.describe_error(code)`</td></tr>
    <tr><td>Hand 2 flash log export</td><td>`wuji_hand_2_export_flash_logs` + `wuji_hand_2_flash_log_export_free`</td><td>`hand.export_flash_logs()`</td></tr>
    <tr><td>Hand connect (USB SN)</td><td>`wuji_hand_connect_sn(sn, alias, &dev)`</td><td>`WujiHand.connect_sn(sn, alias)`</td></tr>
    <tr><td>Hand joint state subscribe</td><td>`wuji_hand_subscribe_joint_states`</td><td>`hand.joint_states().subscribe()`</td></tr>
    <tr><td>Hand realtime command</td><td>`wuji_hand_joint_command_publish` + `wuji_hand_joint_command_publisher_send`</td><td>`hand.joint_command().publish().send([...])`</td></tr>
    <tr><td>Hand realtime controller</td><td>`wuji_hand_realtime_controller_open` / `_set_target_position` / `get_actual*`</td><td>`hand.realtime_controller(LowPass(...))`</td></tr>
    <tr><td>Glove time sync</td><td>`wuji_glove_sync_time(dev, &tsr)`</td><td>`glove.sync_time()`</td></tr>
    <tr><td>Glove hand model path</td><td>`wuji_glove_get_hand_model_path` / `wuji_glove_set_hand_model_path`</td><td>`glove.hand_model_path().get()` / `.set(path)`</td></tr>
    <tr><td>SDK user management</td><td>`wuji_create_user` / `wuji_switch_user` / `wuji_list_users`</td><td>`manager.create_user()` / `switch_user()` / `list_users()`</td></tr>
    <tr><td>User data export and import</td><td>`wuji_user_data_export` / `wuji_user_data_preview` / `wuji_user_data_import`</td><td>`manager.export_user_data()` / `preview_user_data()` / `import_user_data()`</td></tr>
    <tr><td>Glove hand model calibration (async)</td><td>`wuji_glove_calibration_start` + `wuji_glove_calibration_try_finish`</td><td>`glove.calibrate()`</td></tr>
    <tr><td>Glove hand model calibration (sync)</td><td>`wuji_glove_calibrate`</td><td>`glove.calibrate_blocking()`</td></tr>
    <tr><td>Glove tactile contact calibration (sync)</td><td>`wuji_glove_calibrate_tactile_blocking`</td><td>`glove.calibrate_tactile_blocking()`</td></tr>
    <tr><td>Disconnect</td><td>`wuji_dev_disconnect` + `wuji_dev_release`</td><td>`device.disconnect()`</td></tr>
  </tbody>
</table>

## CMake project example

C examples are in [`examples/c/`](https://github.com/wuji-technology/wuji-sdk/tree/main/examples/c). Each project includes `CMakeLists.txt`.

| Example | Purpose | Supported Platforms |
| - | - | - |
| `wuji_glove/0_subscribe_callback` | Subscribe to Wuji Glove data | Linux, macOS, Windows |
| `wuji_hand_2/0_subscribe_joint_states` | Subscribe to Wuji Hand 2 joint states | Linux, macOS, Windows |
| `recording/0_record_topics` | Record data with pause and resume | Linux, macOS, Windows |
| Other examples in `wuji_glove/` | Stream output rate control, custom hand model for online IK, SDK user management, and hand model calibration | Linux, macOS |
| Other examples in `wuji_hand_2/` | Control actions, device info, [fingertip tactile data](https://docs.wuji.tech/docs/en/wuji-sdk/latest/wuji-hand-2-tactile.md), stream output rate control, flash-log export, opposition replay, and MIT sweep | Linux, macOS |
| `wuji_hand/` | Subscriptions, publishing, grasp loops, and tactile status | Linux, macOS |

For Windows build steps, see [LLVM-MinGW](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/README.md#windows-with-llvm-mingw) or [MSVC](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/README.md#windows-with-msvc). Minimal linking commands for Linux and macOS follow:

> [tab] Linux
>
> ```bash theme={null}
> cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" -lwuji_sdk_c -o my_app
> LD_LIBRARY_PATH="${SDK}/lib" ./my_app
> ```

> [tab] macOS
>
> ```bash theme={null}
> cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" \
>   -lwuji_sdk_c -Wl,-rpath,"${SDK}/lib" -o my_app
> ./my_app
> ```

Use an absolute path for `${SDK}`, the extracted package directory. In CMake, set `WUJI_SDK_INCLUDE_DIR` to `${SDK}/include`, and set `WUJI_SDK_LIB` to `${SDK}/lib/libwuji_sdk_c.so` on Linux or `${SDK}/lib/libwuji_sdk_c.dylib` on macOS.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.