Onnxruntime c接口说明及动态调用示例
背景:
需要onnx模型推理的功能,直接引用onnxruntime代码会引起编译问题。所以考虑动态加载onnxruntime的动态库完成。C++的接口依然需要源码依赖,所以考虑使用onnxruntime的c接口。
1.How to access Onnxruntime C API:
要访问c api,需要拿到 c api的函数指针,而onnxruntime 的所有capi定义在 一个结构体中:
struct OrtApi {
OrtStatus*(ORT_API_CALL* SetIntraOpNumThreads)(_Inout_ OrtSessionOptions* options, int intra_op_num_threads);
OrtStatus*(ORT_API_CALL* SetSessionGraphOptimizationLevel)(_Inout_ OrtSessionOptions* options, GraphOptimizationLevel graph_optimization_level)NO_EXCEPTION;
OrtStatus*(ORT_API_CALL* SetDimensions)(OrtTensorTypeAndShapeInfo* info, _In_ const int64_t* dim_values, size_t dim_count)NO_EXCEPTION;
OrtStatus*(ORT_API_CALL* GetTensorElementType)(_In_ const OrtTensorTypeAndShapeInfo*, _Out_ enum ONNXTensorElementDataType* out)NO_EXCEPTION;
OrtStatus*(ORT_API_CALL* GetDimensionsCount)(_In_ const OrtTensorTypeAndShapeInfo* info, _Out_ size_t* out)NO_EXCEPTION;
OrtStatus*(ORT_API_CALL* GetDimensions)(_In_ const OrtTensorTypeAndShapeInfo* info, _Out_ int64_t* dim_values, size_t dim_values_length)NO_EXCEPTION;
OrtStatus*(ORT_API_CALL* GetSymbolicDimensions)(_In_ const OrtTensorTypeAndShapeInfo* info, _Out_ const char** dim_params, size_t dim_params_length)NO_EXCEPTION;
};
上述仅随意列举了用到的函数指针,由于onnxruntime在c api的接口实现中将初始化一个全局静态OrtApi对象,因而这些函数指针并不需要一一获取,只用获取到这个OrtApi对象即可通过访问成员的方式使用对应的函数,极大方便了接口使用。而获取这个对象是通过一个OrtGetApiBase函数实现。见如下定义。
// Interface definition
struct OrtApi;
typedef struct OrtApi OrtApi;
struct OrtApiBase {
const OrtApi*(ORT_API_CALL* GetApi)(uint32_t version)NO_EXCEPTION; // Pass in ORT_API_VERSION
const char*(ORT_API_CALL* GetVersionString)() NO_EXCEPTION;
};
typedef struct OrtApiBase OrtApiBase;
ORT_EXPORT const OrtApiBase* ORT_API_CALL OrtGetApiBase() NO_EXCEPTION;
// Interface Implementation
// onnxruntime/onnxruntime/core/session/onnxruntime_c_api.cc
static constexpr OrtApiBase ort_api_base = {
&OrtApis::GetApi,
&OrtApis::GetVersionString,
};
const OrtApiBase* ORT_API_CALL OrtGetApiBase() NO_EXCEPTION {
return &ort_api_base;
}
首先通过导出函数OrtGetApiBase函数获取指向一个全局静态结构体:OrtApiBase结构体的指针,该结构体内定义了获取包含所用到的函数指针的全局静态OrtApi结构体对象的函数指针GetApi。
因此可以通过如下代码
auto pApiBase = loader.GetFuncPointer<OrtGetApiBasePtr>(
spLibHandle, kOrtGetApiBaseName);
if( nullptr == pApiBase){
// TODO exception.
}
const OrtAp