资讯详情

资讯详情

Cua Driver Native C ABI 深度解析:稳定原生互操作边界的设计与实战

Cua Driver Native C ABI 深度解析稳定原生互操作边界的设计与实战【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cuaCua Driver 在公开的类型化 SDKRust / Python / TypeScript之下维护了一条稳定的原生互操作边界 ——cua_driver_abi.h即 Native C ABI。本文以该 ABI 为绝对核心完整讲解其设计动机、版本化符号约定、不透明句柄与显式缓冲区所有权、异步回调模型、可信会话Trusted Session等关键机制并结合仓库内的头文件、Rust 实现、cbindgen 生成配置与 C 语言冒烟测试给出可直接落地到原生宿主程序的集成方案。读完本文你将能够在任意 C/C或任何支持 C ABI 的语言宿主中安全地创建 Cua Driver 运行时、查询工具清单、异步调用工具并优雅关闭运行时同时理解这一边界为何能让各语言 SDK 独立于实现核心的私有语言。一、这一 ABI 是什么SDK 之下的稳定原生边界在 libs/cua-driver/rust/include/README.md 的定义中cua_driver_abi.h是位于公开 Cua Driver SDK 之下的稳定原生互操作边界stable native interoperability boundary。发布归档会把头文件放置在平台共享库旁边意味着任何语言的调用方只需要头文件 动态库即可接入无需引入 Rust 工具链或 UniFFI。这条边界的定位可以概括为三点为原生嵌入而生需要把 Cua Driver 内嵌进 C/C 进程例如自定义桌面助手、宿主应用、中间件时C ABI 是官方支持的接入面。让语言 SDK 与实现语言解耦Rust、Python、TypeScript SDK 都通过这同一条 C 边界与核心交互而不是依赖实现核心的私有语言内部机制。比 UniFFI 更保守、更可控abi.rs 的模块注释明确指出这里导出的函数“刻意比 UniFFI 生成的 ABI 更小、更保守”使用版本化符号、不透明句柄、调用方可见的所有权语义和状态码使未来任何非 Rust 的原生核心都可以在不实现 UniFFI 内部机制的情况下复现同一契约。术语澄清UniFFI 会生成其私有的 FFI scaffolding 以及 Python/TypeScript 绑定但那是实现特定的脚手架不是稳定公共契约cua_driver_*_v1符号才是一条公开的、可长期依赖的 C 契约见 libs/cua-driver/README.md 中“Repository Layout”一节。二、头文件从哪来cbindgen 生成与 CI 防漂移cua_driver_abi.h不是手写的而是由 Rust 侧#[repr(C)]导出类型通过 cbindgen 生成。文件头部明确写着/* Generated from cua-driver-sdk/src/abi.rs by cua-driver-abi-header. Do not edit. */生成管线位于 abi_header.rs读取 cbindgen.toml 配置对crates/cua-driver-sdk执行 cbindgen生成后做一处关键修正将Optionextern C fn在 C 声明中还原为可空函数指针CuaDriverCompletionV1 callbackRust 的Optionextern C fn与 C 的可空函数指针 ABI 兼容支持--check模式对比既有头文件若不一致则报错退出CI 用该模式保证“实现与分发头文件永不漂移”需要重新生成时运行cargo run -p cua-driver-bindgen --bin cua-driver-abi-header。cbindgen.toml中的[export] include白名单精确列出了要暴露给 C 的全部符号宏常量、结构体、枚举、句柄类型与 16 个_v1函数exclude则隐藏了 Rust 内部的ffi模块私有辅助符号[enum]段将变体重命名为ScreamingSnakeCase并前缀类型名如CUA_DRIVER_STATUS_OK[fn]段为每个导出函数统一加上CUA_DRIVER_API前缀该宏在 Windows 上展开为__declspec(dllexport/dllimport)在其他平台上展开为__attribute__((visibility(default)))。三、四大设计支柱版本化、不透明句柄、显式所有权、异步回调原文档点名的四个机制构成了整条 ABI 的地基1. 版本化符号versioned symbols所有导出函数都以_v1结尾如cua_driver_create_v1宏常量同时声明 ABI 版本#define CUA_DRIVER_ABI_MAJOR 1 #define CUA_DRIVER_ABI_MINOR 1 #define CUA_DRIVER_ABI_PATCH 0 #define DRIVER_ENVELOPE_VERSION 1 #define PRIVATE_WORKER_PROTOCOL_VERSION 1Rust 侧的常量定义在 abi.rs实现与头文件共用同一份数值。调用方在创建驱动之前必须先做版本协商调用cua_driver_abi_version_v1读取运行时 ABI 版本再用cua_driver_abi_is_compatible_v1(major, minor)确认兼容。兼容规则在 abi.rs 中定义major必须完全相等且调用方编译时的minor必须小于等于运行时的minor—— 即主版本严格锁定次版本向后兼容。2. 不透明句柄opaque handles三个句柄类型均为前向声明的透明结构体struct tag 只声明、不定义调用方只能持有指针永远无法触碰内部字段typedef struct CuaDriverHandle CuaDriverHandle; // 驱动运行时 typedef struct CuaDriverOperation CuaDriverOperation; // 一次异步操作的令牌 typedef struct CuaDriverSessionHandle CuaDriverSessionHandle; // 已绑定授权上下文的会话Rust 侧对应实现abi.rsCuaDriverHandle内部是ArcDriverRuntimeCuaDriverSessionHandle内部是ArcRuntimeSessionCuaDriverOperation内部是带AtomicBool取消标志和Notify唤醒原语的操作状态。不透明性保证未来内部表示可以自由演进同时保持 ABI 字节级稳定。3. 显式缓冲区所有权explicit buffer ownershipABI 返回给调用方的字节缓冲区使用显式所有权模型typedef struct { uint8_t *data; size_t len; size_t capacity; } CuaDriverBuffer;调用方持有该缓冲区后必须用cua_driver_buffer_free_v1释放释放空缓冲区是无害操作重复调用同样无害。Rust 侧实现abi.rs用Vec::from_raw_parts精确还原 RustVec的堆内存后 drop随后把结构体清零data 置 null、len/capacity 归 0从而保证幂等。调用方把指针传给free后原结构体即被清空可安全重复调用。4. 回调驱动的异步callbacks for asynchronous work耗时的工具调用与关闭流程都是异步的通过完成回调收尾typedef void (*CuaDriverCompletionV1)(void *context, CuaDriverStatus status, CuaDriverBuffer result, CuaDriverBuffer error);契约要点头文件注释 abi.rs 实现双重印证回调恰好被调用一次除非进程终止result与error两个缓冲区都是调用方所有回调内必须自行cua_driver_buffer_free_v1回调在 ABI 内部的多线程 Tokio 执行器2 个 worker 线程线程名cua-driver-abi见 abi.rs上被调用因此回调不得执行阻塞操作且必须是线程安全的每个异步调用返回一个CuaDriverOperation *令牌取消用cua_driver_operation_cancel_v1完成后用cua_driver_operation_release_v1释放。四、稳定的状态码语义CuaDriverStatus是横跨整条 ABI 的统一返回类型取值为 08映射关系由 abi.rs 与头文件共同锁定枚举值含义CUA_DRIVER_STATUS_OK0成功CUA_DRIVER_STATUS_INVALID_ARGUMENT1参数非法如 JSON 解析失败、工具名非法、配置冲突CUA_DRIVER_STATUS_NULL_POINTER2必需的指针参数为 NULLCUA_DRIVER_STATUS_RUNTIME_UNAVAILABLE3运行时不可用如 ABI 执行器创建失败CUA_DRIVER_STATUS_SHUTDOWN4运行时已关闭不再接受操作CUA_DRIVER_STATUS_CANCELLED5异步操作被取消CUA_DRIVER_STATUS_INTERNAL6内部错误如 JSON 序列化失败CUA_DRIVER_STATUS_PANIC7核心 panic 已被捕获未跨越 C 边界CUA_DRIVER_STATUS_RUNTIME_CONFLICT8进程内已存在直接 Cua Driver 运行时状态码的稳定性有测试背书abi.rs 断言CuaDriverStatus::Ok 0、Panic 7、RuntimeConflict 8并验证CuaDriverAbiVersion结构体大小为 12 字节4 字节 struct_size 3×2 字节 2 字节保留。值得一提的安全设计是with_ffi_guardabi.rs所有_v1导出函数都包裹在catch_unwind中Rust panic 永远不会穿越 C 边界而是被转换成CUA_DRIVER_STATUS_PANIC和一条固定错误消息no panic crossed the C ABI。对应测试 abi.rs 直接验证了这一行为。五、生命周期 API从创建到优雅关闭5.1 创建运行时CUA_DRIVER_API CuaDriverStatus cua_driver_create_v1(const uint8_t *options_json, size_t options_len, CuaDriverHandle **out_handle, CuaDriverBuffer *out_error);options_json可以为空NULL/0表示默认配置非空则必须是 UTF-8 的 JSON 对象out_handle成功时写入新句柄失败时置为 NULLout_error失败时写入调用方所有的错误消息缓冲区。5.2 可用性查询与销毁CuaDriverStatus cua_driver_is_available_v1(CuaDriverHandle *handle, bool *out_available, CuaDriverBuffer *out_error); void cua_driver_destroy_v1(CuaDriverHandle **handle);is_available_v1反映运行时是否仍接受操作内部对应runtime.is_running()destroy_v1接收指针的指针销毁后把外层指针清为 NULL因此重复调用无害 —— 这就是原文档强调的“release functions accept pointer-to-pointer values and are idempotent after clearing them”。5.3 优雅关闭CuaDriverStatus cua_driver_shutdown_v1(CuaDriverHandle *handle, CuaDriverCompletionV1 callback, void *context, CuaDriverOperation **out_operation, CuaDriverBuffer *out_error);关闭也是异步的停止新操作准入stop admission、排空已准入的调用drain admitted calls、回收 SDK 自有资源。调用方需等待回调完成然后cua_driver_operation_release_v1释放令牌。关闭后is_available_v1应返回 falsec_abi_smoke.c 对此有专门断言。六、查询 API元数据与工具清单CuaDriverStatus cua_driver_metadata_json_v1(CuaDriverHandle *handle, CuaDriverBuffer *out_json, CuaDriverBuffer *out_error); CuaDriverStatus cua_driver_list_tools_json_v1(CuaDriverHandle *handle, CuaDriverBuffer *out_json, CuaDriverBuffer *out_error);两者都返回调用方所有的 UTF-8 JSON 缓冲区。元数据 JSON 由 abi.rs 生成包含driver_versionCargo 包版本、contract_version、tools_list_schema_version、capability_version、mcp_protocol_version、pid当前进程号、embedded: true表明这是进程内嵌入式运行时。工具清单 JSON 返回的是“规范的 SDK/MCP 工具清单”即runtime.tools_list()的序列化结果。这两类查询是宿主程序在调用任何工具前进行能力发现capability discovery的标准入口。七、异步工具调用invoke 与可信会话调用7.1 直接调用CuaDriverStatus cua_driver_invoke_v1(CuaDriverHandle *handle, const uint8_t *name, size_t name_len, const uint8_t *arguments_json, size_t arguments_len, CuaDriverCompletionV1 callback, void *context, CuaDriverOperation **out_operation, CuaDriverBuffer *out_error);参数校验abi.rs非常严格工具名必须非空且为合法 UTF-8arguments_json必须是一个 JSON 对象否则返回INVALID_ARGUMENT回调与out_operation均不可为 NULL。内部实现把调用提交到abi_executor()通过spawn_completion包装tokio::select!同时等待任务完成与取消信号任务 panic 会被转换为JoinError从而不会穿越回调或导出函数见 abi.rs。7.2 通过可信会话调用CuaDriverStatus cua_driver_session_invoke_v1(CuaDriverSessionHandle *handle, const uint8_t *name, size_t name_len, const uint8_t *arguments_json, size_t arguments_len, CuaDriverCompletionV1 callback, void *context, CuaDriverOperation **out_operation, CuaDriverBuffer *out_error);签名与直接调用一致区别在于授权上下文已经在创建会话时被“绑定”进句柄每次调用无需重复携带授权信息。其实现abi.rs直接使用RuntimeSession::invoke并且实现中特别注释持锁贯穿整个同步 FFI 调用防止并发close()释放指针后session_invoke才拿到底层会话见 abi.rs。八、可信会话宿主专用授权机制CuaDriverStatus cua_driver_session_create_v1(CuaDriverHandle *handle, const uint8_t *options_json, size_t options_len, CuaDriverSessionHandle **out_session, CuaDriverBuffer *out_error); void cua_driver_session_destroy_v1(CuaDriverSessionHandle **handle);这是host API而非 agent 工具。头文件注释强调返回的句柄把权威authority保存在内存中无法从公开的 session ID 重建 —— 也就是说仅凭一个公开 ID 无法伪造出可用的会话句柄安全边界在句柄本身。options_json接受AbiTrustedSessionOptionsabi.rs字段包括public_session必填公开会话 ID不能为空modePermissionMode枚举指定该会话的权限模式ttl_seconds/idle_ttl_seconds会话 TTL 与空闲 TTLcapability_manifest_path/bounded_manifest_path可选二者是同一含义的新旧别名冲突时报INVALID_ARGUMENT能力清单文件路径transport_session可选仅 Rust 进程内桥接接受不属于公开生成记录或任何 agent 可见工具 schema宿主生成的生命周期租约身份。创建时 ABI 会加载并校验能力清单构造DelegatedSessionRequest然后调用runtime.create_trusted_session。创建失败时RuntimeUnavailable错误映射为SHUTDOWN其余授权错误映射为INVALID_ARGUMENT。销毁时session_destroy_v1会撤销该会话连接绑定的授权授予revoke its connection-bound grants。九、运行时创建选项options JSON 详解cua_driver_create_v1的options_json解析为AbiDriverOptionsabi.rs两个字段claude_code_compatibilitybool默认 false开启 Claude Code computer-use 兼容模式对应 README 中--claude-code-computer-use-compat的能力。authorization可选对象不可变的授权天花板immutable authorization ceiling即整个运行时所有会话的授权上限。authorization对象的字段AbiRuntimeAuthorizationOptionsabi.rs字段类型说明allowed_modesPermissionMode[]允许的权限模式集合构成SessionModeCeilingcompatibility_modePermissionMode兼容模式下使用的权限模式compatibility_capability_manifest_pathstring?兼容能力清单路径新名compatibility_bounded_manifest_pathstring?同一含义的废弃别名与新名冲突时报错unrestricted_acknowledgedbool是否已确认允许 unrestricted 模式max_session_ttl_secondsu64会话最大 TTLmax_idle_ttl_secondsu64会话最大空闲 TTL两个关键校验行为abi.rsfail closed未知字段一律拒绝AbiDriverOptions与授权选项都标注了deny_unknown_fields多传任何未知字段都会返回INVALID_ARGUMENT环境变量一致性检查显式传入的授权配置必须与受信任的环境变量配置一致否则拒绝。涉及的环境变量包括PERMISSION_MODE_ENV、DANGEROUS_BYPASS_ENV、DISABLE_UNRESTRICTED_ENV禁用 unrestricted 的管理配置、CAPABILITY_MANIFEST_FILE_ENV及其废弃别名SESSION_POLICY_FILE_ENV、CAPABILITY_MANIFEST_APPROVED_ENV等。例如显式授权里包含Unrestricted模式但环境中设置了DISABLE_UNRESTRICTED_ENV就会直接拒绝。不传authorization时等价于RuntimeOptions::embedded(claude_code_compatibility)即默认嵌入配置。十、完整 C 集成示例对照仓库冒烟测试仓库自带的 c_abi_smoke.c 是唯一官方的 C 语言端到端示例完整演示了“版本协商 → 创建 → 可用性查询 → 元数据 → 工具清单 → 异步调用 → 异步关闭 → 销毁”全流程可直接作为集成模板。其核心骨架如下/* 1. 版本协商必须在创建驱动前完成 */ CuaDriverAbiVersion version {0}; if (cua_driver_abi_version_v1(version) ! CUA_DRIVER_STATUS_OK || version.struct_size ! sizeof(CuaDriverAbiVersion) || version.major ! CUA_DRIVER_ABI_MAJOR || !cua_driver_abi_is_compatible_v1(CUA_DRIVER_ABI_MAJOR, CUA_DRIVER_ABI_MINOR)) { /* 版本不兼容拒绝继续 */ } /* 2. 创建驱动空 options 默认配置 */ CuaDriverHandle *driver NULL; CuaDriverBuffer error {0}; if (cua_driver_create_v1(NULL, 0, driver, error) ! CUA_DRIVER_STATUS_OK || driver NULL) { /* 读取 error 缓冲区中的消息然后 cua_driver_buffer_free_v1(error) */ } /* 3. 元数据与工具清单返回调用方所有用后必须 free */ CuaDriverBuffer metadata {0}; cua_driver_metadata_json_v1(driver, metadata, error); /* 检查 metadata 中包含 embedded:true ... */ cua_driver_buffer_free_v1(metadata); CuaDriverBuffer tools {0}; cua_driver_list_tools_json_v1(driver, tools, error); /* 检查工具清单中包含 get_desktop_state ... */ cua_driver_buffer_free_v1(tools); /* 4. 异步调用回调在内部执行器线程上被调用 */ static void complete(void *context, CuaDriverStatus status, CuaDriverBuffer result, CuaDriverBuffer error) { CompletionState *state (CompletionState *)context; cua_driver_buffer_free_v1(result); /* 回调内必须释放两个缓冲区 */ cua_driver_buffer_free_v1(error); atomic_store(state-status, (int)status); atomic_store(state-done, 1); } CuaDriverOperation *operation NULL; const char *tool_name some_tool; const char *arguments {}; if (cua_driver_invoke_v1(driver, (const uint8_t *)tool_name, strlen(tool_name), (const uint8_t *)arguments, strlen(arguments), complete, completion, operation, error) ! CUA_DRIVER_STATUS_OK || operation NULL) { return fail(async invocation failed, error); } /* 等待回调置位 completion.done检查 status CUA_DRIVER_STATUS_OK */ cua_driver_operation_release_v1(operation); /* 5. 异步关闭等待完成后再销毁 */ cua_driver_shutdown_v1(driver, complete, completion, operation, error); /* 等待回调确认 is_available_v1 返回 false */ /* 6. 销毁句柄指针的指针重复调用无害 */ cua_driver_destroy_v1(driver); if (driver ! NULL) { /* 销毁后必须已被清空为 NULL */ }示例中值得注意的细节回调上下文CompletionState使用stdatomic.h的原子变量传递完成标志与状态正确应对回调在另一个线程触发的场景wait_for_completion采用usleep(1000)轮询最多等待 2 秒演示了宿主侧的标准等待模式示例刻意验证了幂等性对metadata连续调用两次cua_driver_buffer_free_v1、对operation连续释放两次、对driver连续销毁两次全部安全无害 —— 这正是 ABI 所有权契约“idempotent after clearing”的直接体现冒烟测试调用一个不存在的工具名c_abi_smoke_missing_tool同样以OK状态返回工具错误通过 result/error 内容表达验证了异步调用通道本身对未知工具是健壮的。十一、测试与质量保障ABI 稳定性的三道防线生成检查abi_header.rs的--check模式在 CI 中比对生成头文件与入库头文件防止手改漂移见 libs/cua-driver/README.md 的说明。Rust 单元测试abi.rsabi_layout_and_status_values_are_stable锁定结构体大小、状态码数值、版本兼容矩阵(1,0)、(1,1)兼容(1,2)、(2,0)不兼容generated_header_exposes_the_exported_v1_contract直接把头文件文本编译进测试逐一断言全部宏、全部状态码、全部 16 个导出符号都存在panic_is_contained_as_status验证 panic 被转换为CUA_DRIVER_STATUS_PANIC且错误消息含 no panic crossedowned_buffers_and_handles_are_idempotently_released验证 buffer 与 handle 的双重释放幂等abi_can_own_two_runtime_handles_concurrently验证单进程可同时持有多个驱动句柄cancellation_completes_once_and_release_is_idempotent验证取消后回调恰好触发一次Cancelled状态且释放幂等。C 端冒烟测试c_abi_smoke.c 用纯 C 编译器 头文件完整走通真实调用链证明头文件本身可独立编译、链接并正确运行。十二、各语言 SDK 如何共享同一边界一个容易被忽略但很关键的事实Rust 类型化 SDK 自身也刻意走这条 C 边界。abi.rs 的注释明确指出安全 Rust SDK 通过 C 链接方式#[link_name cua_driver_*_v1]把导出符号重新导入回来而不是绕过边界直接调用内部 Rust 函数 —— 这样 Rust 与 Python、TypeScript、C 消费者处于同一条 ABI 接缝上任何一侧的行为差异都会在边界处被暴露和测试到。NativeAbiDriverabi.rs正是所有语言 SDK 共用的“版本化原生句柄的 Rust 安全包装”即使核心静态链接在同一发行包内也全部经由 C ABI。Pythoncua_driver与 TypeScripttrycua/cua-driver包根目录则通过 UniFFI 生成的绑定调用同一个进程内原生运行时见 libs/cua-driver/README.md 的“Integration surfaces”一节对需要绕过 UniFFI、直接做原生嵌入的场景cua_driver_abi.h就是那条公开、稳定、语言无关的接缝。结语Cua Driver Native C ABI 是一条小而严谨的稳定契约版本化符号解决长期演进不透明句柄封装实现细节显式缓冲区所有权杜绝内存泄漏歧义回调加操作令牌的异步模型适配真实 GUI 自动化工作负载指针-指针释放与清空语义保证幂等。如果你需要在原生进程中嵌入 Cua Driver —— 无论是自定义宿主、中间件还是跨语言桥接 —— 头文件 cua_driver_abi.h、实现 abi.rs 与冒烟测试 c_abi_smoke.c 三份文件即是权威参考前者是契约中间是语义后者是可运行的完整示例。【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →