6.3 C++11 Accessing C99 SDK
Overview
C++11 projects can call the C99 SDK headers and import library directly through extern "C" . This keeps the interface flat, minimizes dependencies, and uses the C-style ArmHandle* lifecycle.
Use Cases
| Scenario | Description |
|---|---|
| Minimal dependencies | Only depend on the public C99 headers and the C/C++ standard library |
| Legacy projects | The project still uses C++11 and is not ready to move to C++17 |
| Platform compatibility | A flat ABI and manual lifecycle management are required |
Header Include
cpp
extern "C" { // Use C linkage for C99 SDK headers in a C++11 project
#include "c_arm_api.h" // Include the C99 SDK top-level header
} // End C linkage declarationMinimal Integration Example
Example code:
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 Configuration
Complete CMake file:
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")Build and Run
powershell
powershell -ExecutionPolicy Bypass -File example/cpp11/c99_connect_get_version/build/build.ps1Build script:
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.exeNotes:
- The build script prepares dependencies from
output/release/c99-sdk/. - To switch devices before running, update the controller and teach-pendant addresses in the example.
Thread Model
When C++11 uses the C99 interface, the thread model is the same as C99:
- Synchronous calls run on the caller thread.
- Periodic tasks run on the session-specific network thread, such as
Arm_Info_AcquireAccess()andArm_Jogging_ContinuousMove(). - Subscription callbacks are triggered when WebSocket messages arrive.
See 1.3 Thread Model.
Compared with the C++17 SDK
| Feature | C++11 + C99 | C++17 SDK |
|---|---|---|
| Entry style | extern "C" + ArmHandle* | Arm object |
| Return style | Status code + out parameters | STATUS_CODE / std::pair |
| Resource management | Manual Destroy | RAII automatic release |
| Container returns | Caller-managed arrays | std::vector / std::string |
| Scope | Legacy projects and minimal dependency integration | New projects and object-oriented API |
Example List
The example/cpp11 directory provides examples aligned with example/c99 .
| Example | Description |
|---|---|
arm_connect_disconnect | Core create/connect/disconnect/destroy |
info_basic | All Arm Info interfaces |
alarm_query | All Arm Alarm interfaces |
motion_basic | All Arm Motion interfaces |
program_execution | Arm Program, BasScript, ArmProgramPose |
registers_basic | All Arm Registers interfaces |
signals_basic | All Arm Signals interfaces |
trajectory_basic | Arm Trajectory and Arm RealTimeTrajectory |
file_manager_basic | All Arm FileManager interfaces |
coordinate_system_basic | All Arm CoordinateSystem interfaces |
modbus_basic | All Arm Modbus interfaces |
jogging_basic | All Arm Jogging interfaces |
extension_basic | All Arm Extension interfaces |
sub_pub_basic | All Arm SubPub interfaces |
c99_connect_get_version | Minimal integration example |
Notes
- Put C99 headers inside
extern "C". - Release
ArmHandle*manually withArm_Destroy(). - Check every return value.
- Do not access the same
ArmHandle*concurrently from multiple threads.