> ## 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 接口（`libwuji_sdk_c.so` + `wuji_sdk.h`），与 Python 接口语义一致。安装方式与 Python 并列见 [安装与环境](/docs/wuji-sdk/quick-start#安装)。

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

完整 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)。

## 初始化与约定

**初始化**

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

```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 用户与标定数据](/docs/wuji-sdk/device-params#sdk-用户管理)。

## 错误码描述

`wuji_hand_2_describe_error` 是静态函数（无需设备连接），把设备故障码（来自 `joint_diagnostics` 的 `error_code_current`，与 Python SDK 错误历史、标定结果携带的是同一套码值）解码到 `WujiErrorInfo`。函数只接受设备故障码。Python SDK 的标定结果中另有编码器专用的错误字节，属不同枚举，不可传入本函数。Wuji Hand 关节诊断（`wuji_hand_get_all_diagnostics` 返回）的 `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`。`severity` 取值：`Warning` / `DeferredStop` / `ImmediateStop` / `Fatal`。`clear_policy` 取值：`AutoClear` / `ManualClear` / `NonClearable`。

## 使用约束

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 的对应接口。跨设备能力的完整用法见上方导语列出的能力章，设备专属接口见本页对应小节。

<div style={{overflowX: "auto"}}>
  <table>
    <thead>
      <tr><th className="nowrap">功能</th><th className="nowrap">C</th><th className="nowrap">Python</th></tr>
    </thead>

    <tbody>
      <tr><td className="nowrap">初始化</td><td className="nowrap"><code>wuji\_init(NULL)</code></td><td className="nowrap"><code>SdkManager.instance()</code></td></tr>
      <tr><td className="nowrap">扫描</td><td className="nowrap"><code>wuji\_scan(\&devs, \&count)</code></td><td className="nowrap"><code>manager.scan()</code></td></tr>
      <tr><td className="nowrap">连接</td><td className="nowrap"><code>wuji\_connect(\&target, alias, \&opts, \&dev)</code></td><td className="nowrap"><code>manager.connect(...)</code> / <code>manager.auto\_connect(...)</code></td></tr>
      <tr><td className="nowrap">连接选项默认值</td><td className="nowrap"><code>wuji\_connect\_options\_default()</code></td><td className="nowrap"><code>ConnectOptions()</code></td></tr>
      <tr><td className="nowrap">设备订阅</td><td className="nowrap"><code>wuji\_glove\_subscribe\_tactile(dev, cb, user, \&sub)</code></td><td className="nowrap"><code>glove.tactile().subscribe\_with\_callback(...)</code></td></tr>
      <tr><td className="nowrap">全局订阅</td><td className="nowrap"><code>wuji\_subscribe\_tf(cb, user, \&sub)</code></td><td className="nowrap"><code>manager.tf().subscribe()</code></td></tr>
      <tr><td className="nowrap">订阅流输出率</td><td className="nowrap"><code>wuji\_sub\_set\_rate(sub, hz, \&actual)</code></td><td className="nowrap"><code>sub.set\_rate(hz)</code></td></tr>
      <tr><td className="nowrap">Hand 2 控制动作</td><td className="nowrap"><code>wuji\_hand\_2\_enable(dev, mask)</code></td><td className="nowrap"><code>hand.enable(joints=mask)</code></td></tr>
      <tr><td className="nowrap">Hand 2 实时指令</td><td className="nowrap"><code>wuji\_hand\_2\_joint\_command\_publish</code> + <code>wuji\_joint\_command\_publisher\_send</code></td><td className="nowrap"><code>hand.joint\_command().publish().send(\[...])</code></td></tr>
      <tr><td className="nowrap">Hand 2 关节状态订阅</td><td className="nowrap"><code>wuji\_hand\_2\_subscribe\_joint\_states</code></td><td className="nowrap"><code>hand.joint\_states().subscribe()</code></td></tr>
      <tr><td className="nowrap">Hand 2 关节诊断订阅</td><td className="nowrap"><code>wuji\_hand\_2\_subscribe\_joint\_diagnostics</code></td><td className="nowrap"><code>hand.joint\_diagnostics().subscribe()</code></td></tr>
      <tr><td className="nowrap">Hand 2 IMU 订阅</td><td className="nowrap"><code>wuji\_hand\_2\_subscribe\_imu</code></td><td className="nowrap"><code>hand.imu().subscribe()</code></td></tr>
      <tr><td className="nowrap">Hand 2 错误码描述</td><td className="nowrap"><code>wuji\_hand\_2\_describe\_error(code, \&info)</code></td><td className="nowrap"><code>WujiHand2.describe\_error(code)</code></td></tr>
      <tr><td className="nowrap">Hand 2 Flash 日志导出</td><td className="nowrap"><code>wuji\_hand\_2\_export\_flash\_logs</code> + <code>wuji\_hand\_2\_flash\_log\_export\_free</code></td><td className="nowrap"><code>hand.export\_flash\_logs()</code></td></tr>
      <tr><td className="nowrap">Hand 连接（USB SN）</td><td className="nowrap"><code>wuji\_hand\_connect\_sn(sn, alias, \&dev)</code></td><td className="nowrap"><code>WujiHand.connect\_sn(sn, alias)</code></td></tr>
      <tr><td className="nowrap">Hand 关节状态订阅</td><td className="nowrap"><code>wuji\_hand\_subscribe\_joint\_states</code></td><td className="nowrap"><code>hand.joint\_states().subscribe()</code></td></tr>
      <tr><td className="nowrap">Hand 实时指令</td><td className="nowrap"><code>wuji\_hand\_joint\_command\_publish</code> + <code>wuji\_hand\_joint\_command\_publisher\_send</code></td><td className="nowrap"><code>hand.joint\_command().publish().send(\[...])</code></td></tr>
      <tr><td className="nowrap">Hand 实时控制器</td><td className="nowrap"><code>wuji\_hand\_realtime\_controller\_open</code> / <code>\_set\_target\_position</code> / <code>*get\_actual*\*</code></td><td className="nowrap"><code>hand.realtime\_controller(LowPass(...))</code></td></tr>
      <tr><td className="nowrap">Glove 时间同步</td><td className="nowrap"><code>wuji\_glove\_sync\_time(dev, \&tsr)</code></td><td className="nowrap"><code>glove.sync\_time()</code></td></tr>
      <tr><td className="nowrap">Glove 手部模型路径</td><td className="nowrap"><code>wuji\_glove\_get\_hand\_model\_path</code> / <code>wuji\_glove\_set\_hand\_model\_path</code></td><td className="nowrap"><code>glove.hand\_model\_path().get()</code> / <code>.set(path)</code></td></tr>
      <tr><td className="nowrap">SDK 用户管理</td><td className="nowrap"><code>wuji\_create\_user</code> / <code>wuji\_switch\_user</code> / <code>wuji\_list\_users</code></td><td className="nowrap"><code>manager.create\_user()</code> / <code>switch\_user()</code> / <code>list\_users()</code></td></tr>
      <tr><td className="nowrap">用户数据导入导出</td><td className="nowrap"><code>wuji\_user\_data\_export</code> / <code>wuji\_user\_data\_preview</code> / <code>wuji\_user\_data\_import</code></td><td className="nowrap"><code>manager.export\_user\_data()</code> / <code>preview\_user\_data()</code> / <code>import\_user\_data()</code></td></tr>
      <tr><td className="nowrap">Glove 手部模型标定（异步）</td><td className="nowrap"><code>wuji\_glove\_calibration\_start</code> + <code>wuji\_glove\_calibration\_try\_finish</code></td><td className="nowrap"><code>glove.calibrate()</code></td></tr>
      <tr><td className="nowrap">Glove 手部模型标定（同步）</td><td className="nowrap"><code>wuji\_glove\_calibrate</code></td><td className="nowrap"><code>glove.calibrate\_blocking()</code></td></tr>
      <tr><td className="nowrap">Glove 触觉接触标定（同步）</td><td className="nowrap"><code>wuji\_glove\_calibrate\_tactile\_blocking</code></td><td className="nowrap"><code>glove.calibrate\_tactile\_blocking()</code></td></tr>
      <tr><td className="nowrap">断开</td><td className="nowrap"><code>wuji\_dev\_disconnect</code> + <code>wuji\_dev\_release</code></td><td className="nowrap"><code>device.disconnect()</code></td></tr>
    </tbody>
  </table>
</div>

## 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/`（订阅关节状态、控制动作、设备信息、[指尖触觉数据](/docs/wuji-sdk/wuji-hand-2-tactile)、设置订阅流输出率、Flash 日志导出、对掌回放与 MIT 扫频）与 `examples/c/wuji_hand/`（订阅、发布、抓握循环与触觉状态）子目录，构建步骤参见该目录 README。最小链接方式：

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

其中 `${SDK}` 是解压后的 tarball 根目录。CMake 工程通过 `-DWUJI_SDK_INCLUDE_DIR` 与 `-DWUJI_SDK_LIB` 指向同样路径。


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