> ## 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 接口参考

Wuji SDK 提供 C 接口（Linux 使用 `libwuji_sdk_c.so`，macOS 使用 `libwuji_sdk_c.dylib`，头文件均为 `wuji_sdk.h`），与 Python 接口语义一致。安装方式与 Python 并列见 [安装与环境](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/quick-start.md#安装)。

本页覆盖 C 侧的初始化约定、内存与回调约束、错误码解码与工程构建。设备专属的 C 接口随各产品文档给出：[Wuji Hand 2 SDK 接口](https://docs.wuji.tech/docs/zh/wuji-hand/latest/sdk-reference.md)与 [Wuji Glove SDK 与数据参考](https://docs.wuji.tech/docs/zh/wuji-glove/latest/sdk-data-reference/index.md)。跨设备通用能力在各能力章按「操作 / Python / C」三列并列给出：[设备发现与连接](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-connection.md)、[SDK 用户与标定数据](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-params.md)、[数据订阅机制](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/data-subscription.md)、[时间同步与坐标变换](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/time-sync.md)与[手部重定向](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/retargeting.md)。

完整 typed 回调与结构体定义参见 SDK tarball（从 [wuji-sdk Releases](https://github.com/wuji-technology/wuji-sdk/releases) 下载）解压后的 `include/wuji_sdk.h`，配套 CMake 工程示例与构建说明见 [wuji-sdk 仓库 examples/c/ 目录](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/README.md)。

Wuji Glove 的离线解算、模型查询与输出释放见[离线解算](https://docs.wuji.tech/docs/zh/wuji-glove/latest/offline-pipeline.md)。

MCAP 录制的 C 示例、监控与释放规则见[数据录制](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/data-recording.md#c-录制)。

## 初始化与约定

**初始化**

进程级初始化一次，结束时释放：

```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;
}

// ... 业务逻辑

wuji_shutdown();
```

**返回值分类**

* `WujiStatus` — 多数操作（`wuji_init` / `wuji_scan` / `wuji_connect` / 订阅打开等），`WUJI_STATUS_OK` 表示成功，失败时通过 `wuji_last_error()` 获取当前线程错误描述。
* `int32_t` — 元信息读取（`wuji_dev_serial_number` / `wuji_dev_device_name`）返回写入字节数。
* `uint8_t` — 状态查询 `wuji_dev_is_connected`。
* `void` — `wuji_shutdown` 与资源释放函数。

**资源释放函数**

* `wuji_discovered_free` — `wuji_scan` 后释放设备列表
* `wuji_dev_release` — 与 `wuji_connect` 配套，断开后释放设备句柄
* `wuji_sub_close` — 关闭订阅句柄

**用户信息结构体**

`WujiUserInfo` 含 7 个字段：`user_id`、`display_name`、`description`、`external_id`、`is_default`、`created_at`、`updated_at`。`wuji_update_user` 通过 `WujiUserUpdate` 只传要改的字段，置位 `clear_description` / `clear_external_id` 可清空对应值。用户管理的完整接口清单见 [SDK 用户与标定数据](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-params.md#sdk-用户管理)。

## 错误码描述

`wuji_describe_error(full_code, &info)` 查询 Wuji Hand 2 或 Wuji Glove 的完整码。调用示例与返回码见 [故障日志与错误码](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/device-fault-logs.md#查询错误码)。

`wuji_hand_2_describe_error(code, &info)` 无需连接设备，接收 Wuji Hand 2 的原始整数故障码，例如 `joint_diagnostics.error_code_current`。编码器标定的 `enc1_error_code`、`enc2_error_code` 和 Wuji Hand 关节诊断中的 `WujiHandJointDiagnostics.error_code` 位域不适用。调用示例：

```c theme={null}
WujiErrorInfo info = {0};
// 0x2102 = Overcurrent（ImmediateStop / ManualClear），生产中真实可能命中的故障码
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);
}
```

未知错误码返回 `WUJI_STATUS_ERR_NOT_FOUND`。

## 使用约束

C SDK 用户必须遵守以下约束，否则会出现 use-after-free、死锁或读到失效错误描述：

* typed 回调的 frame 指针仅在回调期间有效，返回后堆字段即被释放。需要保留的数据必须在回调内拷贝出来，不得保存指针。
* 不要在订阅自身的回调里调 `wuji_sub_close`。`close` 会 join worker 线程，在自身回调中调用必死锁。请在外部线程上 close。
* `wuji_last_error()` 返回值仅在同线程下一次 `wuji_*` 调用前有效。需要保留的错误描述应立即拷贝。
* `END` / `ERROR` 是终止帧，回调收到这两类帧后流不再有新数据，但仍需调用 `wuji_sub_close` 释放订阅句柄。
* 字符串 getter 使用两步查询：先用 `buf=NULL, buf_len=0` 获取 `*needed`（所需字节，含 NUL），再分配缓冲第二次调用填充。直接传不足缓冲会返回 `WUJI_STATUS_ERR_BUFFER_TOO_SMALL`，不做截断。
* 整手批量读（`get_all_effort_limit` / `get_all_mit_params`）返回 flat-20 数组 + 在线 bitmap，用 `WUJI_JOINT_ONLINE(mask, i)` 宏判断槽位是否有效，否则读到离线关节的占位值（0 或 NaN）。
* 标定反馈回调在标定 worker 线程触发，`feedback` 指针仅回调期间有效。回调内调用 session 接口不会死锁，SDK 会拦截：`wuji_glove_calibration_wait` 与 `wuji_glove_calibration_try_finish` 返回 `WUJI_STATUS_ERR_INVALID_ARG`，`wuji_glove_calibration_session_free` 把原因记录到 `wuji_last_error()` 并跳过这次释放——session 仍然存活，必须在回调返回后再释放一次。`wuji_glove_calibration_cancel` 可以在回调内安全调用。session 使用完毕后调用 `wuji_glove_calibration_session_free`，标定结果使用完毕后调用 `wuji_glove_calibration_result_free`。
* `WujiUserInfo` 持堆字符串：单个结构用 `wuji_user_info_free`，`wuji_list_users` 返回的数组用 `wuji_user_info_array_free`。

## Python 接口对照

下表按功能列出 C 与 Python 的对应接口。跨设备能力的完整用法见上方导语列出的能力章，设备专属接口见页首列出的产品文档。

<table>
  <thead>
    <tr><th>功能</th><th>C</th><th>Python</th></tr>
  </thead>

  <tbody>
    <tr><td>初始化</td><td>`wuji_init(NULL)`</td><td>`SdkManager.instance()`</td></tr>
    <tr><td>扫描</td><td>`wuji_scan(&devs, &count)`</td><td>`manager.scan()`</td></tr>
    <tr><td>连接</td><td>`wuji_connect(&target, alias, &opts, &dev)`</td><td>`manager.connect(...)` / `manager.auto_connect(...)`</td></tr>
    <tr><td>连接选项默认值</td><td>`wuji_connect_options_default()`</td><td>`ConnectOptions()`</td></tr>
    <tr><td>设备订阅</td><td>`wuji_glove_subscribe_tactile(dev, cb, user, &sub)`</td><td>`glove.tactile().subscribe_with_callback(...)`</td></tr>
    <tr><td>全局订阅</td><td>`wuji_subscribe_tf(cb, user, &sub)`</td><td>`manager.tf().subscribe()`</td></tr>
    <tr><td>订阅流输出率</td><td>`wuji_sub_set_rate(sub, hz, &actual)`</td><td>`sub.set_rate(hz)`</td></tr>
    <tr><td>Hand 2 控制动作</td><td>`wuji_hand_2_enable(dev, mask)`</td><td>`hand.enable(joints=mask)`</td></tr>
    <tr><td>Hand 2 实时指令</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 关节状态订阅</td><td>`wuji_hand_2_subscribe_joint_states`</td><td>`hand.joint_states().subscribe()`</td></tr>
    <tr><td>Hand 2 关节诊断订阅</td><td>`wuji_hand_2_subscribe_joint_diagnostics`</td><td>`hand.joint_diagnostics().subscribe()`</td></tr>
    <tr><td>Hand 2 IMU 订阅</td><td>`wuji_hand_2_subscribe_imu`</td><td>`hand.imu().subscribe()`</td></tr>
    <tr><td>Hand 2 错误码描述</td><td>`wuji_hand_2_describe_error(code, &info)`</td><td>`WujiHand2.describe_error(code)`</td></tr>
    <tr><td>Hand 2 Flash 日志导出</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 连接（USB SN）</td><td>`wuji_hand_connect_sn(sn, alias, &dev)`</td><td>`WujiHand.connect_sn(sn, alias)`</td></tr>
    <tr><td>Hand 关节状态订阅</td><td>`wuji_hand_subscribe_joint_states`</td><td>`hand.joint_states().subscribe()`</td></tr>
    <tr><td>Hand 实时指令</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 实时控制器</td><td>`wuji_hand_realtime_controller_open` / `_set_target_position` / `get_actual*`</td><td>`hand.realtime_controller(LowPass(...))`</td></tr>
    <tr><td>Glove 时间同步</td><td>`wuji_glove_sync_time(dev, &tsr)`</td><td>`glove.sync_time()`</td></tr>
    <tr><td>Glove 手部模型路径</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 用户管理</td><td>`wuji_create_user` / `wuji_switch_user` / `wuji_list_users`</td><td>`manager.create_user()` / `switch_user()` / `list_users()`</td></tr>
    <tr><td>用户数据导入导出</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 手部模型标定（异步）</td><td>`wuji_glove_calibration_start` + `wuji_glove_calibration_try_finish`</td><td>`glove.calibrate()`</td></tr>
    <tr><td>Glove 手部模型标定（同步）</td><td>`wuji_glove_calibrate`</td><td>`glove.calibrate_blocking()`</td></tr>
    <tr><td>Glove 触觉接触标定（同步）</td><td>`wuji_glove_calibrate_tactile_blocking`</td><td>`glove.calibrate_tactile_blocking()`</td></tr>
    <tr><td>断开</td><td>`wuji_dev_disconnect` + `wuji_dev_release`</td><td>`device.disconnect()`</td></tr>
  </tbody>
</table>

## CMake 工程示例

完整可运行 C 工程（含 `CMakeLists.txt` + 订阅回调示例）见 [wuji-sdk 仓库的 examples/c/ 目录](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/README.md)，按设备分别存放在 `examples/c/wuji_glove/`（设置订阅流输出率、在线 IK 自定义手部模型、SDK 用户管理与手部模型标定）、`examples/c/wuji_hand_2/`（订阅关节状态、控制动作、设备信息、[指尖触觉数据](https://docs.wuji.tech/docs/zh/wuji-sdk/latest/wuji-hand-2-tactile.md)、设置订阅流输出率、Flash 日志导出、对掌回放与 MIT 扫频）与 `examples/c/wuji_hand/`（订阅、发布、抓握循环与触觉状态）子目录，构建步骤参见该目录 README。最小链接方式：

> [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 arm64
>
> ```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
> ```

`${SDK}` 使用发行包解压目录的绝对路径。CMake 项目将 `WUJI_SDK_INCLUDE_DIR` 设为 `${SDK}/include`，将 `WUJI_SDK_LIB` 设为 `${SDK}/lib/libwuji_sdk_c.so`（Linux）或 `${SDK}/lib/libwuji_sdk_c.dylib`（macOS）。


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