跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++AI算法

ONNX Runtime C++ 库集成与推理指南

介绍如何在 C++ 项目中集成 ONNX Runtime 库进行模型推理。内容包括获取预编译库或源码编译方法,解析 C++ API 结构(Env, Session, Value 等),详细阐述基础推理流程(环境创建、会话加载、张量准备、运行推理及结果处理)。提供完整的 C++ 代码示例及用于生成测试模型的 Python 脚本,并给出 Linux/macOS 和 Windows 下的编译运行命令。

板砖工程师发布于 2026/3/27更新于 2026/5/2934 浏览

ONNX Runtime C++ 库集成与推理指南

ONNX Runtime 为 C++ 提供了完整的推理 API,你可以通过集成它来在 C++ 项目中高效地运行 ONNX 模型。

一、如何获取 ONNX Runtime C++ 库

在你的 C++ 项目中使用 ONNX Runtime,主要有两种方式:

  • 使用预编译库(推荐):这是最简单的入门方式。你可以从 ONNX Runtime 官方网站的 Releases 页面下载适用于你平台(如 Windows、Linux、macOS)的 C/C++ 预编译库。这些库通常包含了核心的推理功能。
  • 从源码编译:如果你有特殊需求,比如需要支持特定的硬件(如 GPU、OpenVINO、NNAPI),或希望定制库的大小(例如为移动端进行精简),则需要从源码编译。官方 GitHub 仓库提供了详细的 构建指南。例如,在 Linux 下启用 CUDA 支持的基本步骤是:
git clone --recursive https://github.com/microsoft/onnxruntime.git
cd onnxruntime
./build.sh --config RelWithDebInfo --build_shared_lib --use_cuda

二、C++ API 的结构

ONNX Runtime 的 C++ API 是 C API 的一个'头文件-only'的封装,设计得比较现代,符合 C++ 的使用习惯。核心的 API 都包含在两个主要的头文件中:

  • onnxruntime_cxx_api.h:这是 C++ 开发主要使用的头文件。它定义了 Ort:: 命名空间下的所有 C++ 类,如 Env(环境)、Session(推理会话)、MemoryInfo(内存信息)、Value(张量)等。这些类利用 RAII(资源获取即初始化)机制自动管理内存,并通过抛出异常来处理错误,让代码更简洁安全。
  • onnxruntime_c_api.h:这是底层的 C API,提供了 OrtApi 结构体,包含所有以 Ort 开头的函数(如 OrtCreateSession)。C++ API 是基于此实现的。虽然可以直接使用 C API,但通常更推荐使用更方便的 C++ 封装。

三、C++ 基础推理流程

在 C++ 中使用 ONNX Runtime 进行模型推理,一般遵循以下几个典型步骤:

  1. 包含头文件:在你的代码中包含 ONNX Runtime 的头文件。
#include <onnxruntime_cxx_api.h>
#include <vector>
// ... 其他标准头文件
  1. 创建环境和会话选项:首先,创建一个 Ort::Env 对象来管理推理环境的日志和全局状态。然后,创建 Ort::SessionOptions 对象来配置会话,例如设置优化级别、线程数等。
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
Ort::SessionOptions session_options;
session_options.SetIntraOpNumThreads(1);
// 如果需要,可以在这里添加其他执行提供程序,如 CPU、CUDA 等
  1. 加载模型并创建会话:使用上一步创建的环境和选项,加载模型文件(.onnx)并创建 Ort::Session 对象。会话是执行推理的核心对象。
const char* model_path = "path/to/your/model.onnx";
Ort::Session session(env, model_path, session_options);
  1. 准备输入数据:
    • 获取输入输出信息:通过 session.GetInputCount()、session.GetInputName()、session.GetInputTypeInfo() 等方法,动态获取模型期望的输入名称、维度(shape)和数据类型。
    • 构建输入张量:将你的数据(例如预处理后的图像数据)填充到 std::vector 中。然后,使用 Ort::Value::CreateTensor() 创建一个 ONNX Runtime 张量,你需要提供数据指针、数据大小、维度信息以及数据的内存信息。
  2. 运行推理:调用 session.Run() 方法,传入输入张量的名称和值,以及你想要获取的输出张量名称。函数会返回一个 std::vector<Ort::Value>,包含了推理结果。
const char* input_names[] = {"input"};
const char* output_names[] = {"output"};
std::vector<Ort::Value> input_tensors; // ... 创建并填充 input_tensors ...
auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_names, input_tensors.data(), 1, output_names, 1);
  1. 处理输出:从返回的 Ort::Value 对象中提取数据,并进行后续处理,例如解析分类结果或显示检测框。

四、完整示例

#include <onnxruntime_cxx_api.h>
#include <vector>
#include <iostream>
#include <exception>

int main() {
    try {
        // 1. 创建推理环境(指定日志级别和名称)
        Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "example");
        
        // 2. 配置会话选项
        Ort::SessionOptions session_options;
        session_options.SetIntraOpNumThreads(1); // 线程数
        
        // 若要使用 GPU,可在此添加 CUDA 执行提供程序(需编译时启用 CUDA)
        // OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);
        
        // 3. 加载 ONNX 模型(请替换为你的模型路径)
        const std::string model_path = "linear_model.onnx";
        Ort::Session session(env, model_path.c_str(), session_options);
        
        // 4. 获取模型输入/输出信息
        Ort::AllocatorWithDefaultOptions allocator;
        
        // 输入信息
        size_t num_inputs = session.GetInputCount();
        std::vector<const char*> input_names;
        std::vector<Ort::AllocatedStringPtr> input_names_ptr;
        std::vector<std::vector<int64_t>> input_shapes;
        
        std::cout << "Number of inputs: " << num_inputs << std::endl;
        for (size_t i = 0; i < num_inputs; ++i) {
            auto name = session.GetInputNameAllocated(i, allocator);
            std::cout << "Input [" << i << "] name: " << name.get() << std::endl;
            input_names_ptr.push_back(std::move(name));
            auto type_info = session.GetInputTypeInfo(i);
            auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
            auto shape = tensor_info.GetShape();
            input_shapes.push_back(shape);
            std::cout << " shape: [ ";
            for (auto dim : shape) std::cout << dim << " ";
            std::cout << "]" << std::endl;
        }
        
        // 输出信息
        size_t num_outputs = session.GetOutputCount();
        std::vector<const char*> output_names;
        std::vector<Ort::AllocatedStringPtr> output_names_ptr;
        std::cout << "Number of outputs: " << num_outputs << std::endl;
        for (size_t i = 0; i < num_outputs; ++i) {
            auto name = session.GetOutputNameAllocated(i, allocator);
            std::cout << "Output [" << i << "] name: " << name.get() << std::endl;
            output_names_ptr.push_back(std::move(name));
        }
        
        // 构建名称指针数组(用于 Run 接口)
        for (const auto& ptr : input_names_ptr) input_names.push_back(ptr.get());
        for (const auto& ptr : output_names_ptr) output_names.push_back(ptr.get());
        
        // 5. 准备输入数据(以第一个输入的 shape 为准)
        // 假设第一个输入形状为 [1, 10] 的 float 张量
        const std::vector<int64_t>& first_input_shape = input_shapes[0];
        size_t input_size = 1;
        for (auto dim : first_input_shape) input_size *= dim;
        
        std::vector<float> input_data(input_size);
        for (size_t i = 0; i < input_size; ++i) {
            input_data[i] = static_cast<float>(i); // 填充一些测试数据
        }
        
        // 创建 CPU 内存信息
        Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
        
        // 创建输入张量
        Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
            memory_info, input_data.data(), input_data.size(), first_input_shape.data(), first_input_shape.size()
        );
        
        // 6. 运行推理
        std::vector<Ort::Value> input_tensors;
        input_tensors.push_back(std::move(input_tensor));
        std::vector<Ort::Value> output_tensors = session.Run(
            Ort::RunOptions{nullptr},
            input_names.data(),
            input_tensors.data(),
            input_tensors.size(),
            output_names.data(),
            output_names.size()
        );
        
        // 7. 处理输出(假设输出为 float 张量)
        float* output_data = output_tensors[0].GetTensorMutableData<float>();
        auto output_info = output_tensors[0].GetTensorTypeAndShapeInfo();
        auto output_shape = output_info.GetShape();
        size_t output_count = output_info.GetElementCount();
        
        std::cout << "Output shape: [ ";
        for (auto dim : output_shape) std::cout << dim << " ";
        std::cout << "]" << std::endl;
        std::cout << "Output data: ";
        for (size_t i = 0; i < output_count; ++i) {
            std::cout << output_data[i] << " ";
        }
        std::cout << std::endl;
        
    } catch (const Ort::Exception& e) {
        std::cerr << "ONNX Runtime error: " << e.what() << std::endl;
        return -1;
    } catch (const std::exception& e) {
        std::cerr << "Standard error: " << e.what() << std::endl;
        return -1;
    }
    return 0;
}

如何生成测试模型(Python)

上述示例需要一个 ONNX 模型。以下 Python 脚本可生成一个简单的线性模型 linear_model.onnx(输入 x 形状为 [1,10],输出 y 形状为 [1,10]):

import onnx
from onnx import helper, TensorProto, numpy_helper
import numpy as np

# 创建随机权重和偏置
W = np.random.randn(10, 10).astype(np.float32)
b = np.random.randn(10).astype(np.float32)

# 定义输入输出
x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [1, 10])
y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [1, 10])

# 创建初始值
W_initializer = numpy_helper.from_array(W, name='W')
b_initializer = numpy_helper.from_array(b, name='b')

# 创建节点(Gemm 实现线性变换 y = x * W^T + b)
node = helper.make_node('Gemm', inputs=['x', 'W', 'b'], outputs=['y'])

# 构建图
graph = helper.make_graph([node], 'linear_graph', [x], [y], initializer=[W_initializer, b_initializer])

# 构建模型
model = helper.make_model(graph, producer_name='example')

# 保存模型
onnx.save(model, 'linear_model.onnx')
print("模型已保存为 linear_model.onnx")

运行该脚本生成模型文件,然后将 model_path 指向该文件。

编译与运行

Linux / macOS

假设 ONNX Runtime 安装在 /path/to/onnxruntime,编译命令如下:

g++ -std=c++11 -I/path/to/onnxruntime/include \
-L/path/to/onnxruntime/lib -lonnxruntime example.cpp -o example

如果 ONNX Runtime 安装到了系统路径(如 /usr/local),可以简化:

g++ -std=c++11 example.cpp -lonnxruntime -o example

运行前确保动态库路径可找到(Linux 上可设置 LD_LIBRARY_PATH):

export LD_LIBRARY_PATH=/path/to/onnxruntime/lib:$LD_LIBRARY_PATH
./example
Windows

使用 Visual Studio 开发人员命令提示符:

cl /EHsc /I C:\path\to\onnxruntime\include example.cpp ^ 
/link /LIBPATH:C:\path\to\onnxruntime\lib onnxruntime.lib

运行前将 onnxruntime.dll 放在可执行文件目录或系统路径中。

说明

  • 代码自动获取输入张量的实际形状并分配数据,但假设数据类型为 float。如果你的模型输入是其他类型(如 int64),需要相应调整 CreateTensor 的模板参数和数据填充。
  • 如果模型有多个输入,需要为每个输入创建一个 Ort::Value 并放入 input_tensors 向量,同时确保输入名称顺序与模型一致。
  • 错误处理统一使用 try-catch,ONNX Runtime 的 C++ API 在出错时会抛出 Ort::Exception。
  • 如需 GPU 支持,可在 session_options 中添加相应的执行提供程序(如 OrtSessionOptionsAppendExecutionProvider_CUDA),并确保 ONNX Runtime 库为 GPU 版本。

目录

  1. ONNX Runtime C++ 库集成与推理指南
  2. 一、如何获取 ONNX Runtime C++ 库
  3. 二、C++ API 的结构
  4. 三、C++ 基础推理流程
  5. 四、完整示例
  6. 如何生成测试模型(Python)
  7. 创建随机权重和偏置
  8. 定义输入输出
  9. 创建初始值
  10. 创建节点(Gemm 实现线性变换 y = x * W^T + b)
  11. 构建图
  12. 构建模型
  13. 保存模型
  14. 编译与运行
  15. Linux / macOS
  16. Windows
  17. 说明
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 城市花园小区维修管理系统的设计与实现
  • 基于 Microi 吾码的服务器虚拟化资源管理方案
  • ClawdBot 实战:Whisper tiny 本地转写与 LibreTranslate 双引擎容灾
  • Agent / RAG / MCP / Skill 通用工程解法与技术选型
  • AI 智能体开发提效:Docker 与 Docker Compose 常用命令指南
  • Z-Image i2L 本地 AI 绘画工具快速入门与参数调优
  • CTFShow Web 命令执行 29-124 实战通关指南
  • 大模型、Sora 与世界模型的关系及对自动驾驶的意义
  • 数据结构:递归算法核心原理与实现
  • 鸿蒙 Flutter 智能家居应用开发实战指南
  • 2025 电赛 E 题视觉追踪系统开源实现
  • OpenClaw 安全风险全解析:AI 助手部署中的权限与数据隐患
  • DeepSeek 各版本说明与优缺点分析
  • OpenClaw 配置飞书机器人完整指南
  • C++ STL 常用容器核心用法解析
  • 眼镜店 AR 在线试戴小程序技术方案
  • Python 基础语法完全指南:变量、数据类型与运算符详解
  • FPGA 验证环境构建:Testbench 编写与 Quartus II+ModelSim 联合仿真
  • 前端响应式进阶:从 vw/vh 到 clamp() 的实战思考
  • Windows 环境下编译运行 llama.cpp 实战指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online