forked from PaddlePaddle/FastDeploy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Doc] add docs for how to develop c api (PaddlePaddle#1385)
* add docs for how to develop c api * add English doc for developing C API * fix api doc * add index
- Loading branch information
Showing
4 changed files
with
297 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
[English](../../en/faq/develop_c_api_for_a_new_model.md) | 中文 | ||
|
||
# FastDeploy给模型新增C API | ||
|
||
## 相关概念 | ||
|
||
FastDeploy的核心代码库的实现是基于C++开发的,为了增强接口的可移植性以及提供多种不同开发语言的SDK,有必要提供一组C API,用来作为不同编程语言沟通的桥梁。 | ||
|
||
按照FastDeploy目前的实现结构,新增一个模型的API通常涉及以下三个部分: | ||
|
||
- Model | ||
|
||
模型接口,提供给用户进行模型创建和载入、预测的功能。 | ||
|
||
- Result | ||
|
||
模型推理的结果 | ||
|
||
- Visualization | ||
|
||
对推理结果进行可视化的功能 | ||
|
||
对于Model, 已经基于C++对需要暴露给使用者的接口进行了实现,所需要做的只是使用C风格的接口基于C++接口再包裹一层。对于Result,需要使用C的结构对推理结果进行重新定义。对可视化函数,也只需要使用C风格的接口对C++接口进行包裹即可。 | ||
|
||
我们对命名规则做一个约定,所有和提供C API有关的结构和函数使用FD_C作为前缀进行命名。当使用C对C++的类进行封装时,采用FD_C_{类名}Wrapper的方式对结构进行命令。如果需要调用C++类中的某个方法,采用FD_C_{类名}Wrapper{方法名}的方式进行命名。 | ||
比如,对于C++中的fastdeploy::RuntimeOption类别,使用C进行封装的形式为 | ||
```c | ||
struct FD_C_RuntimeOptionWrapper { | ||
std::unique_ptr<fastdeploy::RuntimeOption> runtime_option; | ||
} | ||
``` | ||
可以看到,这个结构里面用的其实是C++的内容,所以在C语言里,只使用FD_C_RuntimeOptionWrapper这个结构的指针,通过这个指针对C++的实际实现函数进行调用。比如想要调用RuntimeOption::UseCpu()这个函数,在C语言里的封装如下 | ||
```c | ||
void FD_C_RuntimeOptionWrapperUseCpu(FD_C_RuntimeOptionWrapper fd_c_runtimeoption_wrapper){ | ||
auto& runtime_option = fd_c_runtimeoption_wrapper->runtime_option; | ||
runtime_option->UseCpu(); | ||
} | ||
``` | ||
通过这种方式,FD_C_RuntimeOptionWrapper负责持有C++里实际的类, FD_C_RuntimeOptionWrapper{方法名}负责调用C++里类的方法,实现用户在C语言里使用C API接口访问C++所实现的类和函数。 | ||
## 实现流程 | ||
下面通过给ppseg系列模型提供C API为示例讲述如何在当前框架下进行C API的实现。 | ||
1. 提供表示分割模型结果的数据结构 | ||
打开文件fastdeploy/vision/common/result.h, 里面定义各种不同类别模型预测结果的数据结构,找到SegmentationResult,将下列数据结构用纯C结构进行表示 | ||
```c++ | ||
struct FASTDEPLOY_DECL SegmentationResult : public BaseResult { | ||
std::vector<uint8_t> label_map; | ||
std::vector<float> score_map; | ||
std::vector<int64_t> shape; | ||
bool contain_score_map = false; | ||
ResultType type = ResultType::SEGMENTATION; | ||
} | ||
``` | ||
对应的定义一个C的FD_C_SegmentationResult结构进行表示 | ||
```c | ||
typedef struct FD_C_SegmentationResult { | ||
FD_C_OneDimArrayUint8 label_map; | ||
FD_C_OneDimArrayFloat score_map; | ||
FD_C_OneDimArrayInt64 shape; | ||
FD_C_Bool contain_score_map; | ||
FD_C_ResultType type; | ||
} FD_C_SegmentationResult; | ||
``` | ||
关于FD_C_OneDimArrayUint8之类的表示,可以参考文件c_api/fastdeploy_capi/fd_type.h。 | ||
|
||
之后需要定义两个函数,用来从fastdeploy::SegmentationResult和FD_C_SegmentationResult之间进行相互转化。由于对C++的结构使用了对应的Wrapper结构进行包裹,所以实际定义的是FD_C_SegmentationResultWrapper和FD_C_SegmentationResult之间的转化,对应下面两个函数。 | ||
```c | ||
FASTDEPLOY_CAPI_EXPORT extern FD_C_SegmentationResultWrapper* | ||
FD_C_CreateSegmentationResultWrapperFromCResult( | ||
FD_C_SegmentationResult* fd_c_segmentation_result); | ||
|
||
FASTDEPLOY_CAPI_EXPORT extern void | ||
FD_C_SegmentationResultWrapperToCResult( | ||
FD_C_SegmentationResultWrapper* fd_c_segmentation_result_wrapper, | ||
FD_C_SegmentationResult* fd_c_segmentation_result); | ||
``` | ||
还有其它的几个创建和销毁结构的API函数可以参考示例代码进行补充实现。 | ||
关于各种Result在C API中的实现位置为c_api/fastdeploy_capi/vision/result.cc。 | ||
关于声明各种Wrapper的结构可以参考文件c_api/fastdeploy_capi/types_internal.h 。 | ||
2. 提供模型接口的C API | ||
打开文件fastdeploy/vision/segmentation/ppseg/model.h,里面定义了分割模型的C++接口,即fastdeploy::vision::segmentation::PaddleSegModel类。在C中创建一个Wrapper来表示这个类,为了方便后续对同一类别的模型进行快速定义和实现,c_api/fastdeploy_capi/types_internal.h中定义了宏来快速创建Wrapper,以及从Wrapper中取出所包裹的类的对象。例如定义创建分割类模型的Wrapper的宏为 | ||
```c | ||
#define DEFINE_SEGMENTATION_MODEL_WRAPPER_STRUCT(typename, varname) typedef struct FD_C_##typename##Wrapper { \ | ||
std::unique_ptr<fastdeploy::vision::segmentation::typename> varname; \ | ||
} FD_C_##typename##Wrapper | ||
``` | ||
可以按照那个文件已实现的宏的结构,对其它的宏定义进行补充。 | ||
|
||
声明了结构后,就需要在具体的模型类别目录下进行接口实现了。对应C++的目录结构,创建一个保存分割模型C API的目录c_api/fastdeploy_capi/vision/segmentation/ppseg, 创建文件model.h和model.cc分别声明和实现模型的C接口。 | ||
|
||
通过对照PaddleSegModel类里暴露的方法,目前主要需要实现如下五个接口 | ||
``` | ||
// 创建模型 | ||
FD_C_PaddleSegModelWrapper* | ||
FD_C_CreatePaddleSegModelWrapper( | ||
const char* model_file, const char* params_file, const char* config_file, | ||
FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, | ||
const FD_C_ModelFormat model_format); | ||
// 销毁模型 | ||
void FD_C_DestroyPaddleSegModelWrapper( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper); | ||
// 判断初始化是否成功 | ||
FD_C_Bool FD_C_PaddleSegModelWrapperInitialized( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper); | ||
// 预测单张图 | ||
FD_C_Bool FD_C_PaddleSegModelWrapperPredict( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper, | ||
FD_C_Mat img, FD_C_SegmentationResult* fd_c_segmentation_result); | ||
// 成批预测 | ||
FD_C_Bool FD_C_PaddleSegModelWrapperBatchPredict( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper, | ||
FD_C_OneDimMat imgs, | ||
FD_C_OneDimSegmentationResult* results); | ||
``` | ||
|
||
3. 提供可视化函数C API | ||
|
||
打开文件fastdeploy/vision/visualize/visualize.h,里面有对于不同类型模型推理结果进行可视化的函数。在c_api/fastdeploy_capi/vision/visualize.h中对其进行封装一下。例如在C API中需要定义并实现如下对分割结果进行可视化的函数 | ||
|
||
```c | ||
FD_C_Mat FD_C_VisSegmentation(FD_C_Mat im, | ||
FD_C_SegmentationResult* result, | ||
float weight) | ||
``` | ||
4. 创建example, 测试所添加的C API | ||
在examples目录下,根据所接入的模型的类别,在对应的文件夹下新增目录名c,里面创建c的示例代码和CMakeLists.txt,编译测试,确保使用新增的C API能够正常工作。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
English | [中文](../../cn/faq/develop_c_api_for_a_new_model.md) | ||
|
||
# Adds C API to models | ||
|
||
## Introduction | ||
|
||
The core code library of FastDeploy is implemented based on C++ development. In order to enhance the portability of the interface and provide SDKs for different development languages, it is necessary to provide a set of C APIs to serve as a bridge for communication between different programming languages. | ||
|
||
According to FastDeploy’s current implementation structure, adding C APIs for a model usually involves the following three parts: | ||
|
||
- Model | ||
|
||
Model interface, providing users with functions for model creation and loading, prediction. | ||
|
||
- Result | ||
|
||
The result of model inference | ||
|
||
- Visualization | ||
|
||
Function for visualizing inference results | ||
|
||
For Model, C++ has been used to implement the interfaces that need to be exposed to users. What needs to be done is to use C-style interfaces based on C++ interfaces and wraps them in another structure. For Result, C structures are used to define inference results. For visualization functions, you only need to use C-style interfaces to wrap C++ interfaces. | ||
|
||
We make a convention on naming rules. All structures and functions related to provide C APIs are named with FD_C as a prefix. When using C to encapsulate C++ classes, use FD_C_{class name}Wrapper as the structure name. If you need to define a C interface to call a method in a C++ class, use FD_C_{class name}Wrapper{method name} as the name. For example, for the fastdeploy::RuntimeOption class in C++, use C encapsulation as follows | ||
|
||
```c | ||
struct FD_C_RuntimeOptionWrapper { | ||
std::unique_ptr<fastdeploy::RuntimeOption> runtime_option; | ||
} | ||
``` | ||
|
||
You can see that this structure actually uses C++ data, so in C language, only pointers of FD_C_RuntimeOptionWrapper are used. Through this pointer, call the actual implementation function in C++. For example, if you want to call RuntimeOption::UseCpu() function in C language, | ||
|
||
```c | ||
void FD_C_RuntimeOptionWrapperUseCpu(FD_C_RuntimeOptionWrapper fd_c_runtimeoption_wrapper){ | ||
auto& runtime_option = fd_c_runtimeoption_wrapper->runtime_option; | ||
runtime_option->UseCpu(); | ||
} | ||
``` | ||
In this way, FD_C_RuntimeOptionWrapper is responsible for holding the actual class in C++, and FD_C_RuntimeOptionWrapper{method name} is responsible for calling methods of classes in C++, helping user access classes and functions implemented by c++ using c api interface in c language. | ||
## Implementation process | ||
The following describes how to implement C API for ppseg series models as an example of how to implement C API under the current framework. | ||
1. Provide a data structure that represents segmentation results | ||
Open file fastdeploy/vision/common/result.h, which defines data structures for different types of model prediction results, find SegmentationResult, and use pure C structure to represent the following data structure | ||
```c++ | ||
struct FASTDEPLOY_DECL SegmentationResult : public BaseResult { | ||
std::vector<uint8_t> label_map; | ||
std::vector<float> score_map; | ||
std::vector<int64_t> shape; | ||
bool contain_score_map = false; | ||
ResultType type = ResultType::SEGMENTATION; | ||
} | ||
``` | ||
|
||
Define a C FD_C_SegmentationResult structure for representation correspondingly | ||
|
||
```c | ||
typedef struct FD_C_SegmentationResult { | ||
FD_C_OneDimArrayUint8 label_map; | ||
FD_C_OneDimArrayFloat score_map; | ||
FD_C_OneDimArrayInt64 shape; | ||
FD_C_Bool contain_score_map; | ||
FD_C_ResultType type; | ||
} FD_C_SegmentationResult; | ||
``` | ||
|
||
For representations such as FD_C_OneDimArrayUint8, refer to file c_api/fastdeploy_capi/fd_type.h. | ||
|
||
Then you need to define two functions that convert between fastdeploy::SegmentationResult and FD_C_SegmentationResult. Since a corresponding Wrapper structure in C is used for wrapping C++ structures, what is actually defined is conversion between FD_C_SegmentationResultWrapper and FD_C_SegmentationResult, corresponding to the following two functions. | ||
|
||
```c | ||
FASTDEPLOY_CAPI_EXPORT extern FD_C_SegmentationResultWrapper* | ||
FD_C_CreateSegmentationResultWrapperFromCResult( | ||
FD_C_SegmentationResult* fd_c_segmentation_result); | ||
|
||
FASTDEPLOY_CAPI_EXPORT extern void | ||
FD_C_SegmentationResultWrapperToCResult( | ||
FD_C_SegmentationResultWrapper* fd_c_segmentation_result_wrapper, | ||
FD_C_SegmentationResult* fd_c_segmentation_result); | ||
``` | ||
There are also other API functions for creating and destroying structures that can be implemented by referring to the sample code. | ||
The implementation of various Results in C API is located at c_api/fastdeploy_capi/vision/result.cc. | ||
For declaring various Wrapper structures, refer to file c_api/fastdeploy_capi/types_internal.h . | ||
2. Provide C API for model interface | ||
Open file fastdeploy/vision/segmentation/ppseg/model.h, which defines the C++ interface for segmentation model, i.e. fastdeploy::vision::segmentation::PaddleSegModel class. Create a Wrapper in C to represent this class. For convenience of quick definition and implementation of models of the same category in the future, c_api/fastdeploy_capi/types_internal.h defines macros to quickly create Wrapper and extract the wrapped class object from Wrapper. For example, define a macro to create a Wrapper for segmentation model as | ||
```c | ||
#define DEFINE_SEGMENTATION_MODEL_WRAPPER_STRUCT(typename, varname) typedef struct FD_C_##typename##Wrapper { \ | ||
std::unique_ptr<fastdeploy::vision::segmentation::typename> varname; \ | ||
} FD_C_##typename##Wrapper | ||
``` | ||
|
||
You can supplement other macro definitions referring to the structure of the macros already implemented in that file. | ||
|
||
After declaring the structure, you need to implement the interface in the specific model category directory. Corresponding to C++ directory structure, create a directory c_api/fastdeploy_capi/vision/segmentation/ppseg to save C API for segmentation model, create files model.h and model.cc respectively to declare and implement C API for model. | ||
|
||
By comparing with methods exposed by PaddleSegModel class, currently mainly need to implement following five interfaces | ||
|
||
```c | ||
// Create model | ||
FD_C_PaddleSegModelWrapper* | ||
FD_C_CreatePaddleSegModelWrapper( | ||
const char* model_file, const char* params_file, const char* config_file, | ||
FD_C_RuntimeOptionWrapper* fd_c_runtime_option_wrapper, | ||
const FD_C_ModelFormat model_format); | ||
|
||
// Destroy model | ||
|
||
void FD_C_DestroyPaddleSegModelWrapper( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper); | ||
|
||
// Initilization | ||
|
||
FD_C_Bool FD_C_PaddleSegModelWrapperInitialized( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper); | ||
|
||
// Predict | ||
FD_C_Bool FD_C_PaddleSegModelWrapperPredict( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper, | ||
FD_C_Mat img, FD_C_SegmentationResult* fd_c_segmentation_result); | ||
|
||
// Batch prediction | ||
FD_C_Bool FD_C_PaddleSegModelWrapperBatchPredict( | ||
FD_C_PaddleSegModelWrapper* fd_c_paddleseg_model_wrapper, | ||
FD_C_OneDimMat imgs, | ||
FD_C_OneDimSegmentationResult* results); | ||
``` | ||
3. Provide C API for visualization function | ||
Open file fastdeploy/vision/visualize/visualize.h, which has functions for visualizing inference results of different types of models. Wrap them in c_api/fastdeploy_capi/vision/visualize.h. For example, define and implement following function for visualizing segmentation results. | ||
```c | ||
FD_C_Mat FD_C_VisSegmentation(FD_C_Mat im, | ||
FD_C_SegmentationResult* result, | ||
float weight) | ||
``` | ||
|
||
4. Create example to test added C API | ||
|
||
In examples directory, according to category of model, create new directory named c in corresponding folder.Create c sample code and CMakeLists.txt inside, then compile and test it, to ensure that the added C API can work normally. |