Skip to content

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

ScenarioDescription
Minimal dependenciesOnly depend on the public C99 headers and the C/C++ standard library
Legacy projectsThe project still uses C++11 and is not ready to move to C++17
Platform compatibilityA 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 declaration

Minimal Integration Example

Example code:

cpp11/c99_connect_get_version/src/main.cpp
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:

cpp11/c99_connect_get_version/CMakeLists.txt
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.ps1

Build script:

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

Notes:

  • 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() and Arm_Jogging_ContinuousMove() .
  • Subscription callbacks are triggered when WebSocket messages arrive.

See 1.3 Thread Model.

Compared with the C++17 SDK

FeatureC++11 + C99C++17 SDK
Entry styleextern "C" + ArmHandle*Arm object
Return styleStatus code + out parametersSTATUS_CODE / std::pair
Resource managementManual DestroyRAII automatic release
Container returnsCaller-managed arraysstd::vector / std::string
ScopeLegacy projects and minimal dependency integrationNew projects and object-oriented API

Example List

The example/cpp11 directory provides examples aligned with example/c99 .

ExampleDescription
arm_connect_disconnectCore create/connect/disconnect/destroy
info_basicAll Arm Info interfaces
alarm_queryAll Arm Alarm interfaces
motion_basicAll Arm Motion interfaces
program_executionArm Program, BasScript, ArmProgramPose
registers_basicAll Arm Registers interfaces
signals_basicAll Arm Signals interfaces
trajectory_basicArm Trajectory and Arm RealTimeTrajectory
file_manager_basicAll Arm FileManager interfaces
coordinate_system_basicAll Arm CoordinateSystem interfaces
modbus_basicAll Arm Modbus interfaces
jogging_basicAll Arm Jogging interfaces
extension_basicAll Arm Extension interfaces
sub_pub_basicAll Arm SubPub interfaces
c99_connect_get_versionMinimal integration example

Notes

  1. Put C99 headers inside extern "C" .
  2. Release ArmHandle* manually with Arm_Destroy() .
  3. Check every return value.
  4. Do not access the same ArmHandle* concurrently from multiple threads.