Open sdcb opened 3 months ago
您好,我的理解上C API无非是对C++ API再做了一层封装,难度应该不大。您是否能提交一个PR来完成这个工作呢,我可以配合您来完成。(我也很想把该项目移植到C#等其它编程语言中,但是现在确实人手有限)
这是一套可能的设计(可能大语言模型生成):
paddle2onnx_c_api.h
:
#ifndef PADDLE2ONNX_C_API_H
#define PADDLE2ONNX_C_API_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// 默认和C++ API一样的导出逻辑
#if defined(_WIN32)
#ifdef PADDLE2ONNX_C_LIB
#define PADDLE2ONNX_C_API __declspec(dllexport)
#else
#define PADDLE2ONNX_C_API __declspec(dllimport)
#endif
#else
#define PADDLE2ONNX_C_API __attribute__((visibility("default")))
#endif
// 数据结构定义
typedef struct {
char op_name[100];
char export_op_name[100];
} Paddle2ONNX_CustomOp;
typedef struct {
char name[100];
int64_t* shape;
int32_t rank;
int32_t dtype;
} Paddle2ONNX_ModelTensorInfo;
typedef struct {
int64_t background_label;
int64_t keep_top_k;
float nms_eta;
float nms_threshold;
float score_threshold;
int64_t nms_top_k;
bool normalized;
} Paddle2ONNX_NMSParameters;
typedef struct {
Paddle2ONNX_ModelTensorInfo inputs[100];
Paddle2ONNX_ModelTensorInfo outputs[100];
int num_inputs;
int num_outputs;
} Paddle2ONNX_TensorInfoContainer;
// API函数声明
PADDLE2ONNX_C_API int Paddle2ONNX_IsExportable(
const char* model, const char* params, int32_t opset_version,
bool auto_upgrade_opset, bool verbose, bool enable_onnx_checker,
bool enable_experimental_op, bool enable_optimize,
Paddle2ONNX_CustomOp* ops, int op_count, const char* deploy_backend);
PADDLE2ONNX_C_API int Paddle2ONNX_Export(
const char* model, const char* params, char** out, int* out_size,
int32_t opset_version, bool auto_upgrade_opset, bool verbose,
bool enable_onnx_checker, bool enable_experimental_op, bool enable_optimize,
Paddle2ONNX_CustomOp* ops, int op_count, const char* deploy_backend,
char** calibration_cache, int* calibration_size, const char* external_file,
bool* save_external, bool export_fp16_model, char** disable_fp16_op_types,
int disable_fp16_op_types_count);
PADDLE2ONNX_C_API int Paddle2ONNX_RemoveMultiClassNMS(
const char* onnx_model, int model_size, char** out_model, int* out_model_size);
PADDLE2ONNX_C_API int Paddle2ONNX_ConvertFP32ToFP16(
const char* onnx_model, int model_size, char** out_model, int* out_model_size);
#ifdef __cplusplus
}
#endif
#endif // PADDLE2ONNX_C_API_H
这是可能的paddle2onnx_c_api.c
实现:
#include "paddle2onnx_c_api.h"
#include "paddle2onnx/converter.h" // Assume this is the correct path to C++ header
#ifdef __cplusplus
extern "C" {
#endif
// Helper function to convert C CustomOps array to C++ vector
static std::vector<paddle2onnx::CustomOp> ConvertCtoCppCustomOps(Paddle2ONNX_CustomOp* ops, int op_count) {
std::vector<paddle2onnx::CustomOp> cpp_ops(op_count);
for (int i = 0; i < op_count; i++) {
strcpy(cpp_ops[i].op_name, ops[i].op_name);
strcpy(cpp_ops[i].export_op_name, ops[i].export_op_name);
}
return cpp_ops;
}
PADDLE2ONNX_C_API int Paddle2ONNX_IsExportable(
const char* model,
const char* params,
int32_t opset_version,
bool auto_upgrade_opset,
bool verbose,
bool enable_onnx_checker,
bool enable_experimental_op,
bool enable_optimize,
Paddle2ONNX_CustomOp* ops,
int op_count,
const char* deploy_backend) {
try {
std::vector<paddle2onnx::CustomOp> cpp_ops = ConvertCtoCppCustomOps(ops, op_count);
bool result = paddle2onnx::IsExportable(model, params, opset_version,
auto_upgrade_opset, verbose,
enable_onnx_checker, enable_experimental_op,
enable_optimize, cpp_ops.data(), op_count,
deploy_backend);
return result ? 0 : 1;
} catch (...) {
return -1;
}
}
PADDLE2ONNX_C_API int Paddle2ONNX_Export(
const char* model,
const char* params,
char** out, int* out_size,
int32_t opset_version,
bool auto_upgrade_opset,
bool verbose,
bool enable_onnx_checker,
bool enable_experimental_op,
bool enable_optimize,
Paddle2ONNX_CustomOp* ops,
int op_count,
const char* deploy_backend,
char** calibration_cache,
int* calibration_size,
const char* external_file,
bool* save_external,
bool export_fp16_model,
char** disable_fp16_op_types,
int disable_fp16_op_types_count) {
try {
std::vector<paddle2onnx::CustomOp> cpp_ops = ConvertCtoCppCustomOps(ops, op_count);
std::string output;
std::vector<std::string> disabled_ops(disable_fp16_op_types, disable_fp16_op_types + disable_fp16_op_types_count);
bool result = paddle2onnx::Export(model, params, &output, opset_version,
auto_upgrade_opset, verbose, enable_onnx_checker,
enable_experimental_op, enable_optimize,
cpp_ops.data(), op_count, deploy_backend,
nullptr, 0, external_file, save_external, export_fp16_model,
disabled_ops.data(), disable_fp16_op_types_count);
if (result) {
*out_size = output.size();
*out = new char[*out_size];
std::memcpy(*out, output.c_str(), *out_size);
}
return result ? 0 : 1;
} catch (...) {
return -1;
}
}
PADDLE2ONNX_C_API int Paddle2ONNX_RemoveMultiClassNMS(
const char* onnx_model,
int model_size,
char** out_model,
int* out_model_size) {
try {
std::string output;
bool result = paddle2onnx::RemoveMultiClassNMS(onnx_model, model_size, &output);
if (result) {
*out_model_size = output.size();
*out_model = new char[*out_model_size];
std::memcpy(*out_model, output.c_str(), *out_model_size);
}
return result ? 0 : 1;
} catch (...) {
return -1;
}
}
PADDLE2ONNX_C_API int Paddle2ONNX_ConvertFP32ToFP16(
const char* onnx_model,
int model_size,
char** out_model,
int* out_model_size) {
try {
std::string output;
bool result = paddle2onnx::ConvertFP32ToFP16(onnx_model, model_size, &output);
if (result) {
*out_model_size = output.size();
*out_model = new char[*out_model_size];
std::memcpy(*out_model, output.c_str(), *out_model_size);
}
return result ? 0 : 1;
} catch (...) {
return -1;
}
}
#ifdef __cplusplus
}
#endif
请供参考,由于我不太懂cmake的原理,因此希望上面这些代码对您有帮助。
我简单翻了一下代码。
CMake 里有个编译选项: WITH_STATIC
,打开它编译后,配合 header 文件:https://github.com/PaddlePaddle/Paddle2ONNX/blob/develop/paddle2onnx/converter.h 。应该已经算是一个 C API 了。
只是好像没什么文档,我也没有实际跑过。
问题描述 您好,感谢您们对Paddle2ONNX项目的贡献。我在使用Paddle2ONNX进行模型转换时遇到了移植问题。目前只有C++ API,对于我们团队来说,如果有C API的话,将会更容易将该项目移植到C#等其它编程语言中。能否考虑提供一个C API接口?我们相信这会为更多开发者带来便利,非常感谢!
更多信息 :
报错截图 无
其他信息 无