C API Reference
Operations and Appendix
Wuji SDK ships a C API (libwuji_sdk_c.so on Linux or libwuji_sdk_c.dylib on macOS, with wuji_sdk.h on both platforms) with the same semantics as the Python interface. For installation alongside Python, see Installation and Environment.
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 and Wuji Glove SDK and Data Reference. Cross-device capabilities live in the capability chapters, each with an operation / Python / C table: Device Discovery & Connection, SDK Users and Calibration Data, Data Subscription Mechanism, Time Synchronization and Coordinate Transforms, and Hand Retargeting.
The complete typed callback signatures and struct definitions live in include/wuji_sdk.h of the extracted tarball (download it from wuji-sdk Releases). The CMake example and build instructions are in the examples/c/ directory of the wuji-sdk repo.
For Wuji Glove offline computation, model queries, and output cleanup, see Offline Solving.
For C MCAP recording examples, monitoring, and cleanup, see Data Recording.
Initialization and conventions
Initialization
Call once at process start and release at shutdown:
#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_OKmeans success. On failure, retrieve the per-thread error string viawuji_last_error().int32_t— metadata readers (wuji_dev_serial_number/wuji_dev_device_name) return the number of bytes written.uint8_t— status querywuji_dev_is_connected.void—wuji_shutdownand resource cleanup functions.
Resource cleanup functions
wuji_discovered_free— release the device list returned bywuji_scanwuji_dev_release— paired withwuji_connect, release the device handle after disconnectingwuji_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.
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.
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:
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
framepointer 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_closefrom inside that subscription’s own callback.closejoins 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 nextwuji_*call on the same thread. Copy the message immediately if you need to retain it. ENDandERRORare terminal frames — no further data will arrive after them, but you still need to callwuji_sub_closeto release the subscription handle.- String getters use a two-call query: first call with
buf=NULL, buf_len=0to read*needed(required bytes including NUL), then allocate and call again to fill. Passing an undersized buffer returnsWUJI_STATUS_ERR_BUFFER_TOO_SMALLand never truncates. - Whole-hand batch reads (
get_all_effort_limit/get_all_mit_params) return a flat-20 array plus an online bitmap. Use theWUJI_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
feedbackpointer is valid only during the callback. The SDK guards the session calls made from inside it rather than deadlocking:wuji_glove_calibration_waitandwuji_glove_calibration_try_finishreturnWUJI_STATUS_ERR_INVALID_ARG, andwuji_glove_calibration_session_freerecords the reason inwuji_last_error()and skips the release — so the session stays alive and you must free it again after the callback returns.wuji_glove_calibration_cancelis safe to call from the callback. Free the session withwuji_glove_calibration_session_freeand the result withwuji_glove_calibration_result_free. WujiUserInfoholds heap strings: free a single struct withwuji_user_info_free, and free an array returned bywuji_list_userswithwuji_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.
| Capability | C | Python |
|---|---|---|
| Init | wuji_init(NULL) | SdkManager.instance() |
| Scan | wuji_scan(&devs, &count) | manager.scan() |
| Connect | wuji_connect(&target, alias, &opts, &dev) | manager.connect(…) / manager.auto_connect(…) |
| Default connect options | wuji_connect_options_default() | ConnectOptions() |
| Device subscribe | wuji_glove_subscribe_tactile(dev, cb, user, &sub) | glove.tactile().subscribe_with_callback(…) |
| Global subscribe | wuji_subscribe_tf(cb, user, &sub) | manager.tf().subscribe() |
| Stream output rate | wuji_sub_set_rate(sub, hz, &actual) | sub.set_rate(hz) |
| Hand 2 control action | wuji_hand_2_enable(dev, mask) | hand.enable(joints=mask) |
| Hand 2 realtime command | wuji_hand_2_joint_command_publish + wuji_joint_command_publisher_send | hand.joint_command().publish().send([…]) |
| Hand 2 joint state subscribe | wuji_hand_2_subscribe_joint_states | hand.joint_states().subscribe() |
| Hand 2 joint diagnostics subscribe | wuji_hand_2_subscribe_joint_diagnostics | hand.joint_diagnostics().subscribe() |
| Hand 2 IMU subscribe | wuji_hand_2_subscribe_imu | hand.imu().subscribe() |
| Hand 2 error description | wuji_hand_2_describe_error(code, &info) | WujiHand2.describe_error(code) |
| Hand 2 flash log export | wuji_hand_2_export_flash_logs + wuji_hand_2_flash_log_export_free | hand.export_flash_logs() |
| Hand connect (USB SN) | wuji_hand_connect_sn(sn, alias, &dev) | WujiHand.connect_sn(sn, alias) |
| Hand joint state subscribe | wuji_hand_subscribe_joint_states | hand.joint_states().subscribe() |
| Hand realtime command | wuji_hand_joint_command_publish + wuji_hand_joint_command_publisher_send | hand.joint_command().publish().send([…]) |
| Hand realtime controller | wuji_hand_realtime_controller_open / _set_target_position / get_actual* | hand.realtime_controller(LowPass(…)) |
| Glove time sync | wuji_glove_sync_time(dev, &tsr) | glove.sync_time() |
| Glove hand model path | wuji_glove_get_hand_model_path / wuji_glove_set_hand_model_path | glove.hand_model_path().get() / .set(path) |
| SDK user management | wuji_create_user / wuji_switch_user / wuji_list_users | manager.create_user() / switch_user() / list_users() |
| User data export and import | wuji_user_data_export / wuji_user_data_preview / wuji_user_data_import | manager.export_user_data() / preview_user_data() / import_user_data() |
| Glove hand model calibration (async) | wuji_glove_calibration_start + wuji_glove_calibration_try_finish | glove.calibrate() |
| Glove hand model calibration (sync) | wuji_glove_calibrate | glove.calibrate_blocking() |
| Glove tactile contact calibration (sync) | wuji_glove_calibrate_tactile_blocking | glove.calibrate_tactile_blocking() |
| Disconnect | wuji_dev_disconnect + wuji_dev_release | device.disconnect() |
CMake project example
A complete runnable C project (with CMakeLists.txt plus a subscription callback demo) lives in the examples/c/ directory of the wuji-sdk repo, organized into examples/c/wuji_glove/ (stream output rate control, custom hand model for online IK, SDK user management, and hand model calibration), examples/c/wuji_hand_2/ (joint-state subscriptions, control actions, device info, fingertip tactile data, stream output rate control, flash-log export, opposition replay, and MIT sweep), and examples/c/wuji_hand/ (subscriptions, publishing, grasp loops, and tactile status) subdirectories. See that directory’s README for build instructions. Minimal link:
Linux
macOS arm64
cc my_app.c -I "${SDK}/include" -L "${SDK}/lib" -lwuji_sdk_c -o my_app
LD_LIBRARY_PATH="${SDK}/lib" ./my_appcc 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.
ドキュメント