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 支持的基本步骤是:bashgit 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 的头文件。cpp#include <onnxruntime_cxx_api.h> #include <vector> // ... 其他标准头文件
  2. 创建环境和会话选项:首先,创建一个 Ort::Env 对象来管理推理环境的日志和全局状态。然后,创建 Ort::SessionOptions 对象来配置会话,例如设置优化级别、线程数等。cppOrt::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); Ort::SessionOptions session_options; session_options.SetIntraOpNumThreads(1); // 如果需要,可以在这里添加其他执行提供程序,如 CPU、CUDA 等
  3. 加载模型并创建会话:使用上一步创建的环境和选项,加载模型文件(.onnx)并创建 Ort::Session 对象。会话是执行推理的核心对象。cppconst char* model_path = "path/to/your/model.onnx"; Ort::Session session(env, model_path, session_options);
  4. 准备输入数据
    • 获取输入输出信息:通过 session.GetInputCount()session.GetInputName()session.GetInputTypeInfo() 等方法,动态获取模型期望的输入名称、维度(shape)和数据类型。
    • 构建输入张量:将你的数据(例如预处理后的图像数据)填充到 std::vector 中。然后,使用 Ort::Value::CreateTensor() 创建一个 ONNX Runtime 张量,你需要提供数据指针、数据大小、维度信息以及数据的内存信息。
  5. 运行推理:调用 session.Run() 方法,传入输入张量的名称和值,以及你想要获取的输出张量名称。函数会返回一个 std::vector<Ort::Value>,包含了推理结果。cppconst 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);
  6. 处理输出:从返回的 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,编译命令如下:

bash

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

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

bash

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

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

bash

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

Windows

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

bash

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 版本。

Read more

二手平台出现OpenClaw卸载服务,299元可上门“帮卸”;2026年春招AI人才身价暴涨:平均月薪超6万;Meta辟谣亚历山大·王离职 | 极客头条

二手平台出现OpenClaw卸载服务,299元可上门“帮卸”;2026年春招AI人才身价暴涨:平均月薪超6万;Meta辟谣亚历山大·王离职 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * 微信员工辟谣“小龙虾可自动发红包”:不要以讹传讹 * 蚂蚁集团启动春招,超 70% 为 AI 相关岗位 * 受贿 208 万!拼多多一员工被抓 * 2026 年春招 AI 人才身价暴涨: 平均月薪超 6 万元 * 二手平台出现 OpenClaw 上门卸载服务 * 权限太高,国家互联网应急中心发布 OpenClaw 安全应用的风险提示 * 字节豆包内测 AI 电商功能:无需跳转抖音,日活用户数超

By Ne0inhk
遭“美国政府封杀”后,Anthropic正式提起诉讼!

遭“美国政府封杀”后,Anthropic正式提起诉讼!

整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 据路透社报道,当地时间周一,AI 初创公司 Anthropic 正式对美国国防部及特朗普政府提起诉讼,抗议五角大楼将其列为“国家安全供应链风险”主体的决定。 Anthropic 在向美国加州北区地方法院提交的诉讼文件中表示,这一认定“史无前例且非法”,已对公司造成“不可挽回的损害”。公司希望法院撤销该决定,并指示联邦机构停止执行相关认定。 划定 AI 应用红线,双方观点不一 正如我们此前报道,这场争端的核心在于 Anthropic 为其核心 AI 模型 Claude 设定的两条技术使用红线,与美国国防部的使用需求发生根本冲突。 此前,Anthropic 曾与五角大楼签署一份价值最高可达 2 亿美元的合作合同,Claude 也成为少数被纳入美国机密网络环境进行测试的 AI 系统之一。 对此,Anthropic 一直坚持两条底线: * Claude 等技术不得被用于对美国民众的大规模国内监控;

By Ne0inhk
为省5-10美元差点毁库!Claude一条指令删光200万条数据、网站停摆24小时,创始人坦言:全是我的错

为省5-10美元差点毁库!Claude一条指令删光200万条数据、网站停摆24小时,创始人坦言:全是我的错

编译 | 屠敏 出品 | ZEEKLOG(ID:ZEEKLOGnews) AI 时代,一次看似普通的操作,竟能让整套生产环境与近 200 万条数据瞬间「归零」。 近日,数据科学社区 DataTalks.Club 创始人 Alexey Grigorev 就遭遇了这样的惊魂时刻,他在使用 AI 编程工具 Claude Code 管理网站服务器时,意外清空了平台积累 2.5 年的核心数据,甚至连数据库快照也未能幸免,导致网站停摆整整 24 小时。 这起事故不仅在开发者社区引发热议,更给所有依赖 AI 工具与自动化运维的从业者敲响了警钟。事后,Alexey Grigorev 公开复盘了整个过程,并揭露了此次事故的核心问题。让我们一起看看。 一次看似很普通的网站迁移 这场“删库”事件的前因,其实并不复杂。

By Ne0inhk
星标超 28 万,OpenClaw 两天两次大更!适配GPT 5.4,告别“抽卡式 Prompt”

星标超 28 万,OpenClaw 两天两次大更!适配GPT 5.4,告别“抽卡式 Prompt”

整理 | 梦依丹 出品 | ZEEKLOG(ID:ZEEKLOGnews) “We don’t do small releases.” 这是 OpenClaw 在发布 2026.3.7 版本时写下的一句话。 刚刚过去的周六与周日,这个 GitHub 星标已超 28 万 的 AI Agent 开源项目再次迎来两轮重量级更新。 两天两次更新:OpenClaw 做了一次“真正的大版本升级” 打开 OpenClaw 的 GitHub 更新日志,你会发现这次版本更新的规模确实不小。在 3 月 7 日发布更新后,第二天又迅速推出 2026.3.8-beta.1 和

By Ne0inhk