跳到主要内容

推理入门

最小可跑的推理调用链只有三步:打开会话 → 推理一张图 → 关闭。本案例把这三步写成能直接编译运行的代码,六种语言调用的是同一套 C ABI。

本案例的几个要点:

  • 一次打开,反复推理:打开成本只付一次,之后每帧循环调推理;不要每张图重新打开。
  • 每次只喂一张图:没有批量或视频流接口,连续帧就是循环调用同一函数。
  • 激活码只在打开时用一次:推理函数永不收码;已绑机的模型打开时不再要码。
相关页面

分层见 架构。后端选择见 运行时 Provider。缺包与离线部署见 环境准备。失败码与 hint 见 错误码

适用条件

要求
交付物任一语言包,内含 x64 / ARM64 native 库;缺 native 只能编译引用,不能运行
模型加密 .darmodel(钥匙内嵌),或明文 .onnx、.pdmodel、含二者的目录
不接受.pt / .pth(先在 Studio 转 ONNX);Windows 上的 rknn 载荷
运行时对应 Provider 已在本机部署并通过本地校验;SDK 不下载不安装
图像输入编码字节流(JPG / PNG / BMP),或裸像素缓冲(RGB888 / BGR888 等)
平台Windows x64 / Linux x64 / Linux ARM64。macOS 不在 v1

加密模型还额外要求与 Core 信任根匹配的正式签名 Provider;单纯下载或登记成功不等于可运行。

应用场景

  • 第一次接入本 SDK:用一个模型和一张图把整条链路跑通,再往里加业务。
  • 部署后验收:现场机器装完语言包和 Provider,跑一遍本页判断能不能推理,而不是只看安装登记。
  • 手动试跑:产线换模型或换卡后,单张图确认会话能打开、结果 JSON 正常。

关键思路

一个会话 = 一份已加载模型 + 一个已选定的 Provider。多模型或多份同模型就是多开几个会话,接口完全相同;没有模型组或全局引擎入口。

打开   open / open_plain        读容器头或明文探测 → 选 Provider → 验票 / 解密(明文跳过)


推理 infer_image 每次一张图,结果 JSON;连续帧循环调这里


关闭 close / Dispose 释放并清零明文窗口,之后句柄失效

三处最容易踩空的地方:

  1. 打开只做一次。 同路径同选项多次打开会驻留共用一份权重,不会加载多份模型。
  2. 推理是阻塞调用。 耗时随 Provider 与硬件而定,不承诺硬实时;PLC 侧必须在扫描周期外进程 / 线程调用。
  3. 关闭要等在飞推理结束。 禁止与进行中的推理并发调用。

六语言的三步函数名对照:

语言打开推理关闭
Cdarra_session_open / open_plaindarra_session_infer_imagedarra_session_close
C++同 C,共用 darra_ai.h同 C同 C
C#AiSession.Open / OpenPlainInferImageDispose
PythonSession.open / open_plaininfer_imageclose
JavaAiSession.tryOpen / openinferImageclose
RustSession::open / open_plaininfer_imageDrop

各语言完整 API 见 C · C++ · C# · Python · Java · Rust

完整示例

下面每段都是完整可跑的最小程序:打开一个已绑机的加密模型,推理一张编码图片,关闭会话。未激活的出厂包先问激活状态再要一次码,见 初始化

C

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "darra_ai.h"

int main(void)
{
/* 第一件事:核 ABI。不等 = 装错了库,禁止继续 */
if (DARRA_VERSION_DECODE_MAJOR(darra_version()) != DARRA_VERSION_MAJOR) {
fprintf(stderr, "ABI 不匹配: %s\n", darra_version_string());
return 1;
}

/* 打开:已绑机的 .darmodel 后三个参数都传 NULL */
darra_session* s = NULL;
int32_t rc = darra_session_open("model.darmodel", NULL, NULL, NULL, &s);
if (rc != DARRA_OK) {
darra_error_t err;
err.size = sizeof(err);
darra_last_error(&err);
fprintf(stderr, "[%d] %s\n建议: %s\n", err.code, err.message, err.hint);
return (int)rc;
}

/* 读一张编码图 */
FILE* f = fopen("photo.jpg", "rb");
if (f == NULL) { darra_session_close(s); return 1; }
fseek(f, 0, SEEK_END);
long flen = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t* jpg = (uint8_t*)malloc((size_t)flen);
size_t len = fread(jpg, 1, (size_t)flen, f);
fclose(f);

/* 推理:一张图,结果 JSON 由 SDK 分配 */
darra_image_desc desc;
memset(&desc, 0, sizeof(desc));
desc.size = sizeof(darra_image_desc);
desc.format = DARRA_IMAGE_AUTO; /* 编码字节流按魔数自嗅探 */

char* json = NULL;
rc = darra_session_infer_image(s, jpg, len, &desc, &json);
if (rc == DARRA_OK) {
printf("%s\n", json);
darra_string_free(json); /* 堆字符串必须用 darra_string_free */
}

free(jpg);
darra_session_close(s); /* 释放;NULL 安全 */
return (int)rc;
}

MSVC 编译记得加 /utf-8,运行目录必须带 DarraAI.Core.dll。结构体首字段 size 一律填 sizeof(...),漏填返回 DARRA_INTERNAL

C++

与 C 共用同一份 darra_ai.h 导出,不另包一层 C++ 类库,直接把上面的函数换成 extern "C" 调用即可:

#include "darra_ai.h"

extern "C" int run_once() {
darra_session* s = nullptr;
if (darra_session_open("model.darmodel", nullptr, nullptr, nullptr, &s) != DARRA_OK)
return 1;
/* darra_session_infer_image(...) */
darra_session_close(s);
return 0;
}

C#

using Darra.AI.Runtime;

try
{
// 打开:已绑机的 .darmodel 不收激活码
using var session = AiSession.Open("model.darmodel");

// 推理:一张编码图(JPG / PNG / BMP)
byte[] jpg = File.ReadAllBytes("photo.jpg");
string json = session.InferImage(jpg, ImageDesc.Auto());
Console.WriteLine(json);
}
catch (AiException ex)
{
// SDK 不弹窗;错误码与 hint 原样透传,展示与重试由应用负责
Console.Error.WriteLine(ex.Message);
Console.Error.WriteLine(ex.Hint);
}
// Dispose 即关闭,释放并清零明文窗口

明文模型换成 AiSession.OpenPlain("model.onnx", preferProvider: "onnx-cpu") 即可,其余不变。参数与返回值见 推理

Python

from pathlib import Path
from darra_ai import IMAGE_AUTO, Session
from darra_ai.errors import DarraError

jpg = Path("photo.jpg").read_bytes()

try:
with Session.open("model.darmodel") as s: # 已绑机不收码;with 退出即 close
print(s.task, s.provider_id)
print(s.infer_image(jpg, format=IMAGE_AUTO))
except DarraError as ex:
print(ex)

import darra_ai 不加载 native,第一次碰 Core 的 API 才加载。属性与异常见 Session

Java

AiSession.OpenResult r = AiSession.tryOpen("model.darmodel", null);
if (!r.ok()) {
System.err.println(r.info().display());
return;
}
try (AiSession s = r.session()) { // AutoCloseable,退出即 close
byte[] jpg = java.nio.file.Files.readAllBytes(java.nio.file.Path.of("photo.jpg"));
String json = s.inferImage(jpg, ImageDesc.auto());
System.out.println(json);
}

出厂包要一次激活码走 activate / tryActivate,之后本机 open 免密。见 会话

Rust

use darra_ai::{ImageDesc, Session};

fn main() -> Result<(), darra_ai::Error> {
let session = Session::open("model.darmodel", None)?;
let jpeg = std::fs::read("photo.jpg").map_err(|e| darra_ai::Error::IoNotFound {
message: format!("读图片失败:photo.jpg ({e})"),
hint: String::new(),
})?;
let json = session.infer_image(&jpeg, &ImageDesc::auto())?;
println!("{json}");
Ok(())
} // Drop 即 close

操作步骤

  1. 核版本:加载后比较 ABI 主版本,不等就是装错了库,停下来查安装目录。
  2. 准备环境:用 Studio 下载中心或离线整合包部署所需 Provider,见 运行时清单
  3. 问激活状态(只有加密容器需要):先 probe,NeedsCode 时向用户要一次激活码再 activate;已绑机直接打开。
  4. 推理:复用同一个会话反复喂图,读结果 JSON 里随 session.Task 变化的 results
  5. 关闭:所有任务结束后 close / Dispose,等在飞推理结束再关。
注意事项
  • 激活码不是推理密码,只在打开那一步用一次;不要每次推理都弹输入框,也不要把码写进日志。
  • 结果 JSON 的结构随任务类型变化(detect 给 box、classify 给 top-k、segment 给掩码),元数据缺字段是空值,不要按默认 640 / 80 / 17 去补。
  • 裸像素缓冲必须给宽高,且禁止用 Auto(嗅探不出通道序)。
  • 赶时间别在这里压并发:同会话推理内部互斥排队,真要并发走 并行推理 的推理池,或多开会话。