6.3 C++11 接入 C99 接口
概述
C++11 项目可以直接通过 extern "C" 调用 C99 SDK 头文件和导入库。这样做的核心价值是保持接口扁平、依赖最小,并且继续使用 ArmHandle* 这套 C 风格生命周期。
适用场景
| 场景 | 说明 |
|---|---|
| 最小依赖 | 只依赖 C99 公开头和 C/C++ 标准库 |
| 遗留工程 | 项目还停留在 C++11,暂不适合切换到 C++17 |
| 平台兼容 | 需要扁平 ABI 和手动生命周期管理 |
头文件引入
cpp
extern "C" { // C++11 工程中按 C 链接方式引入 C99 SDK 头文件
#include "c_arm_api.h" // 引入 C99 SDK 总头文件
} // 结束 C 链接声明最小接入示例
示例代码
cpp
#include <stdio.h>
extern "C" {
#include "c_arm_api.h"
}
int main(void)
{
// [ZH] 本示例直接在源码中写死连接地址,不解析命令行参数。
// [EN] This example hard-codes the connection addresses in the source code and does not parse command-line arguments.
ArmHandle* handle = Arm_Create();
if (handle == NULL) {
printf("[cpp11_c99_connect_get_version] 创建句柄失败 / Failed to create the handle\n");
return 1;
}
// [ZH] 连接机器人。
// [EN] Connect to the robot.
const int connectRet = Arm_Connect(handle, "10.27.1.2", "10.27.1.102");
if (connectRet != 0) {
printf("[cpp11_c99_connect_get_version] 连接失败 / Connect failed, 状态码 / Status code: %d\n", connectRet);
Arm_Destroy(handle);
return 1;
}
printf("[cpp11_c99_connect_get_version] 机器人连接成功 / Robot connected successfully\n");
// [ZH] 读取控制器版本。
// [EN] Read the controller version.
char version[128] = {0};
const int versionRet = Arm_Info_GetControllerVersion(
handle,
version,
sizeof(version)
);
if (versionRet != 0) {
printf("[cpp11_c99_connect_get_version] 获取版本失败 / Get version failed, 状态码 / Status code: %d\n", versionRet);
Arm_Disconnect(handle);
Arm_Destroy(handle);
return 1;
}
printf("[cpp11_c99_connect_get_version] 控制器版本 / Controller version: %s\n", version);
// [ZH] 断开连接并销毁句柄。
// [EN] Disconnect and destroy the handle.
Arm_Disconnect(handle);
Arm_Destroy(handle);
printf("[cpp11_c99_connect_get_version] 示例结束 / Example finished\n");
return 0;
}CMake 配置
对应完整 CMake 文件:
txt
cmake_minimum_required(VERSION 3.20)
project(c99_connect_get_version LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
add_executable(c99_connect_get_version
src/main.cpp
)
set_target_properties(c99_connect_get_version PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/output")
target_include_directories(c99_connect_get_version PRIVATE src dependency/include)
target_compile_options(c99_connect_get_version PRIVATE /utf-8)
target_link_libraries(c99_connect_get_version PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/dependency/lib/AgilebotCppSdk.lib")编译与运行
powershell
powershell -ExecutionPolicy Bypass -File example/cpp11/c99_connect_get_version/build/build.ps1对应构建脚本:
ps1
param()
chcp 65001 > $null
[Console]::OutputEncoding = [Text.Encoding]::UTF8
# 在示例脚本目录下执行,统一使用相对路径访问工程和产物。
Set-Location $PSScriptRoot
# 清理上一次拷贝的 SDK 依赖与示例运行产物,避免旧 DLL 干扰当前验证。
Remove-Item -Recurse -Force ..\dependency -ErrorAction Ignore
Remove-Item -Recurse -Force ..\output -ErrorAction Ignore
powershell -ExecutionPolicy Bypass -File ..\..\..\build\prepare_dependency.ps1 -Package c99
# 配置并编译当前独立示例工程。
cmake -S .. -B ..\buildcache -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_LINKER_TYPE=LLD
if (Test-Path ..\buildcache\compile_commands.json) {
Copy-Item -Force ..\buildcache\compile_commands.json ..\compile_commands.json
}
cmake --build ..\buildcache
powershell -ExecutionPolicy Bypass -File ..\..\..\build\run_example.ps1 -Executable ..\output\c99_connect_get_version.exe说明:
- 编译脚本会自动从
output/release/c99-sdk/准备依赖。 - 运行前如需切换设备,修改示例中的控制器地址和示教器地址。
线程模型
C++11 通过 C99 接口使用 SDK 时,线程模型与 C99 完全一致:
- 同步调用在调用线程执行
- 周期任务在会话专用网络线程执行,例如
Arm_Info_AcquireAccess()和Arm_Jogging_ContinuousMove() - 订阅回调在 WebSocket 消息到达时触发
详见 1.3 线程模型。
与 C++17 SDK 对比
| 特性 | C++11 + C99 | C++17 SDK |
|---|---|---|
| 入口形态 | extern "C" + ArmHandle* | Arm 对象 |
| 返回方式 | 状态码 + out 参数 | STATUS_CODE / std::pair |
| 资源管理 | 手动 Destroy | RAII 自动释放 |
| 容器返回 | 调用方自己管理数组 | std::vector / std::string |
| 适用范围 | 老工程、最小依赖集成 | 新工程、对象式封装 |
示例列表
example/cpp11 目录提供与 example/c99 对齐的示例代码
| 示例 | 说明 |
|---|---|
arm_connect_disconnect | Core create/connect/disconnect/destroy |
info_basic | Arm Info 全部接口 |
alarm_query | Arm Alarm 全部接口 |
motion_basic | Arm Motion 全部接口 |
program_execution | Arm Program、BasScript、ArmProgramPose |
registers_basic | Arm Registers 全部接口 |
signals_basic | Arm Signals 全部接口 |
trajectory_basic | Arm Trajectory 与 Arm RealTimeTrajectory |
file_manager_basic | Arm FileManager 全部接口 |
coordinate_system_basic | Arm CoordinateSystem 全部接口 |
modbus_basic | Arm Modbus 全部接口 |
jogging_basic | Arm Jogging 全部接口 |
extension_basic | Arm Extension 全部接口 |
sub_pub_basic | Arm SubPub 全部接口 |
c99_connect_get_version | 最小接入闭环示例 |
注意事项
- 头文件必须放在
extern "C"里。 ArmHandle*需要手动Arm_Destroy()释放。- 所有接口都要检查返回值。
- 同一
ArmHandle*不要被多个线程并发乱用。