C++ SDK 概述
C++ 客户与 C 共用同一份 C ABI 头 Core/include/darra_ai.h。头文件用 extern "C" 包住全部导出,永不导出 C++ 类型 / STL。绑定只翻译类型和错误码,不得另造语义。
仓库里 Darra.AI.Studio.SDK/C++/ 是空目录:没有 *.hpp、没有 darra::ai 命名空间、没有异常类型、没有官方 RAII 类。C++ 的「薄封装」= 直接调 C ABI。逐函数说明见 C SDK;语义冲突时以 darra_ai.h 为准。
错误码 hint 文案见 错误码。DARM1 header_json 字段见 元数据。
与 darra_ai.h 的 DARRA_VERSION_MAJOR/MINOR/PATCH 以及 Core CMake PROJECT_VERSION 同一组数字。加载后第一件事核 ABI:DARRA_VERSION_DECODE_MAJOR(darra_version()) == DARRA_VERSION_MAJOR(当前为 1),不等 = 装错了库,禁止继续。
与 C API 的对比
| 特性 | C API | C++ 消费方 |
|---|---|---|
| 头文件 | darra_ai.h | 同一份(extern "C") |
| 资源管理 | darra_session_close / darra_string_free | 同左。SDK 不提供析构封装 |
| 类型 | C 结构体 + darra_session* 不透明句柄 | 同左。ABI 纪律禁止导出 C++ 类 |
| 错误 | int32_t + 线程局部 darra_last_error | 同左。不抛异常 |
| 字符串 | char*,堆串必须 darra_string_free | 同左。禁止 delete[] / 跨 CRT free |
| 进度回调 | darra_progress_cb 函数指针 | 同左。无捕获 lambda 可衰减为函数指针;有状态走 user 指针 |
| 示例 | Core/tools/example_c/main.c | 没有独立 C++ 示例工程 |
#include "darra_ai.h"
int main() {
if (DARRA_VERSION_DECODE_MAJOR(darra_version()) != DARRA_VERSION_MAJOR) {
return 1;
}
darra_session* s = nullptr;
darra_runtime_ensure(nullptr, nullptr, nullptr, nullptr);
int32_t rc = darra_session_open("model.darmodel", "model.darmkey",
nullptr, nullptr, &s);
if (rc != DARRA_OK) {
darra_error_t err{};
err.size = sizeof(err);
darra_last_error(&err);
return (int)rc;
}
darra_session_close(s);
return 0;
}
安装
从 下载 取 C/C++ 内核包(C 与 C++ 不是两套包):
| 成品 | 平台 |
|---|---|
darra-ai-core-windows-x64.zip | Windows x64 |
darra-ai-core-linux-x64.tar.gz | Linux x86_64 |
darra-ai-core-linux-arm64.tar.gz | Linux ARM64(RK3588 板端) |
也可取 darra-ai-c-sdk.zip(头 + lib + 示例)。公开包是 runtime 构建:只有解密 / 验票 / 推理 / 诊断 / 运行时包管理。darra_encrypt_ / darra_issue_ / darra_fingerprint_ 符号不进公开包。
包内(以 Windows zip 为准,见产品说明):darra_ai.h、import lib、运行时库、darra-selftest。CMake 目标名 DarraAI.Core,OUTPUT_NAME darraai_core → Windows darraai_core.dll / darraai_core.lib,Linux libdarraai_core.so。公开清单也写 DarraAI.Core.dll(C# 绑定两种文件名都能加载)。
#include "darra_ai.h"
CMake(消费已安装的头与 import lib,路径按解压位置改):
add_executable(my_app main.cpp)
target_include_directories(my_app PRIVATE ${SDK_PATH}/include)
if(WIN32)
target_link_libraries(my_app PRIVATE ${SDK_PATH}/lib/darraai_core.lib)
target_compile_options(my_app PRIVATE /utf-8) # 头文件 UTF-8 无 BOM,注释全中文
else()
target_link_libraries(my_app PRIVATE darraai_core)
endif()
在本仓库 Core 树内链接 CMake 目标:target_link_libraries(my_app PRIVATE DarraAI.Core)(与 Core/tools/example_c 相同,该示例源是 main.c)。
运行时把 darraai_core.dll(或 libdarraai_core.so)放到可执行文件旁或加载器搜索路径。ORT / CUDA / TensorRT / OpenVINO / RKNN 等重依赖不链进本库,由 darra_runtime_ensure 按硬件下载。
环境要求
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows 10/11 x64;Linux x86_64;Linux ARM64(RK3588) |
| 架构 | 只交付 x64 / ARM64,单调用约定,无 __stdcall 变体 |
| 头文件 | UTF-8 无 BOM。MSVC 加 /utf-8;GCC/Clang 默认 UTF-8 |
| C++ 标准 | 头是 C ABI,不强制 C++17。Core 内部编库才钉 C++17 |
| macOS | v1 不做 |
| 系统驱动 | SDK 不代装 NVIDIA / 板端 NPU 驱动 |
薄封装如何调 C ABI
没有第二套 C++ API。调用顺序与 C 相同:
darra_version 核 ABI →(可选)darra_diag_collect / darra_runtime_ensure → darra_session_open 或 darra_session_open_plain → darra_session_meta_json → darra_session_infer_image → darra_session_close。
| C ABI | C++ 侧怎么写 |
|---|---|
darra_session* | 普通指针。close 后失效 |
char** 出参 | 成功后必须 darra_string_free,禁止 delete[] |
darra_image_desc / darra_session_options / darra_error_t | 栈上结构体,先填 size = sizeof(...) |
darra_progress_cb | void (*)(float, const char*, void*)。回调在 SDK 工作线程;回调内禁止再调任何 darra_* |
| 错误 | rc != DARRA_OK 后立刻在同一线程 darra_last_error。槽是线程局部的,下一次 API 会冲掉 |
nullptr | 对应 C 的 NULL(路径 / Provider / 回调均可空,语义见头文件) |
应用侧若要用 RAII,只能自己包,不是 SDK 类型:
#include "darra_ai.h"
#include <memory>
struct SessionClose {
void operator()(darra_session* p) const noexcept { darra_session_close(p); }
};
using SessionPtr = std::unique_ptr<darra_session, SessionClose>;
堆字符串同样:拿到 char* 后用完 darra_string_free,不要对 SDK 分配的串用 std::string 接管所有权再 delete。
快速开始
仓库权威示例是 C 的 Core/tools/example_c/main.c(用法:darra-example-c <model.darmodel\|model.onnx> [key.darmkey] <image.jpg>)。下面是同一 ABI 的 C++ 写法。
#include "darra_ai.h"
#include <cstdio>
#include <cstring>
#include <fstream>
#include <vector>
static int fail(const char* where, int32_t rc) {
darra_error_t err{};
err.size = sizeof(err);
darra_last_error(&err);
std::fprintf(stderr, "%s 失败 [%d] %s\n建议: %s\n",
where, err.code, err.message, err.hint);
return (int)rc;
}
int main() {
if (DARRA_VERSION_DECODE_MAJOR(darra_version()) != DARRA_VERSION_MAJOR) {
std::fprintf(stderr, "ABI 不匹配,库版本 = %s\n", darra_version_string());
return 1;
}
int32_t rc = darra_runtime_ensure(nullptr, nullptr, nullptr, nullptr);
if (rc != DARRA_OK) return fail("darra_runtime_ensure", rc);
darra_session* session = nullptr;
rc = darra_session_open("model.darmodel", "model.darmkey", nullptr, nullptr, &session);
if (rc != DARRA_OK) return fail("darra_session_open", rc);
char* meta = nullptr;
rc = darra_session_meta_json(session, &meta);
if (rc != DARRA_OK) {
darra_session_close(session);
return fail("darra_session_meta_json", rc);
}
std::printf("[meta] %s\n", meta);
darra_string_free(meta);
std::ifstream in("photo.jpg", std::ios::binary);
std::vector<uint8_t> jpg((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
darra_image_desc desc{};
desc.size = sizeof(desc);
desc.format = DARRA_IMAGE_AUTO;
char* results = nullptr;
rc = darra_session_infer_image(session, jpg.data(), jpg.size(), &desc, &results);
if (rc != DARRA_OK) {
darra_session_close(session);
return fail("darra_session_infer_image", rc);
}
std::printf("[results] %s\n", results);
darra_string_free(results);
darra_session_close(session);
return 0;
}
明文 .onnx(或 .pdmodel / 含 pdmodel+pdiparams 的目录)把 open 换成 darra_session_open_plain(path, nullptr, &session)。.pt / .pth 仍拒,返回 DARRA_UNSUPPORTED_PAYLOAD。
工业相机裸缓冲:format = DARRA_IMAGE_BGR888,必须填 width / height;stride = 0 表示紧凑(BGR = width * 3)。裸缓冲禁止 DARRA_IMAGE_AUTO。
带线程选项用 darra_session_open_ex / darra_session_open_plain_ex,先填 darra_session_options.size。禁止改 Windows ReservedCpuSets、禁止动 PLC 隔离核。
功能对照(均在 darra_ai.h)
| 功能 | C 函数 | 说明 |
|---|---|---|
| 版本 | darra_version / darra_version_string | 打包值与 "1.0.0+runtime" 静态串(禁止释放) |
| 错误 | darra_last_error / darra_clear_error | 线程局部槽 |
| 诊断 | darra_diag_collect | JSON;可能数百毫秒,禁止 PLC 扫描周期调用 |
| Provider 包 | darra_runtime_ensure / darra_runtime_ensure_cancel | 幂等;进程内互斥;进度回调内禁止再调 API |
| 加密容器 | darra_session_open / open_ex | .darmodel;key 与密码至少给一个 |
| 明文模型 | darra_session_open_plain / open_plain_ex | .onnx / Paddle 明文 |
| 元信息 | darra_session_meta_json | 派生 JSON,缺字段不编 640/80/17 |
| 推理 | darra_session_infer_image | v1 单张图,不做视频流;不承诺硬实时 |
| 关闭 | darra_session_close | NULL 安全;禁止与在飞调用并发 |
open 时对应 Provider 未装会内部 ensure 一次(无进度回调)。指名 Provider 不可用 = fail-closed,不静默降级。
authoring
darra_encrypt_onnx / darra_issue_key / darra_fingerprint_perturb 仅在 DARRA_AUTHORING=ON 的构建里导出(只随 AI Studio)。runtime 库物理上没有这些符号。头文件声明包在 #ifdef DARRA_AUTHORING 里;链接 runtime 再引用 = 链接/加载失败。调用顺序:扰动 → 加密 → 签发。
诚实边界
- 不承诺 dump 免疫。
- 加密单向:官方不解回明文;永久密码只用于无限次推理。
- 驱动不代装。
- macOS 不在 v1;Windows 上 rknn 载荷返回
DARRA_UNSUPPORTED_PAYLOAD。 - 推理是阻塞调用,不承诺硬实时。