|
| 1 | +English | [中文](../../cn/faq/develop_c_sharp_api_for_a_new_model.md) |
| 2 | + |
| 3 | +# Adds C# API to models |
| 4 | + |
| 5 | +## Introduction |
| 6 | + |
| 7 | +The core code library of FastDeploy is implemented based on C++ development. In order to provide C# interface for users to call, C interface needs to be used as a bridge for communication. Usually when adding C# API for a model, C API is needed to implement first, then develop C# API. C# will call C interface, and C interface will call C++ interface to implement specific functions. About how to add C API for a model, please refer to document [Adds C API to models](./develop_c_api_for_a_new_model.md). |
| 8 | + |
| 9 | +According to FastDeploy’s current implementation structure, adding an API for a model usually involves following three parts: |
| 10 | + |
| 11 | +- Model |
| 12 | + |
| 13 | +Model interface, provide users with functions for model creation and loading, prediction. |
| 14 | + |
| 15 | +- Result |
| 16 | + |
| 17 | +Inference result of model |
| 18 | + |
| 19 | +- Visualization |
| 20 | + |
| 21 | +Function for visualizing inference result |
| 22 | + |
| 23 | +Since C# is an object-oriented programming language, C# interface forms of each part need to be consistent with corresponding interfaces of C++, giving users the same usage experience. Since C# interface is implemented by calling underlying C interface, it is necessary to understand how C# calls C interface and relationship between data structures of both. Please refer to [C# Marshal](https://learn.microsoft.com/en-us/dotnet/framework/interop/marshalling-data-with-platform-invoke). |
| 24 | + |
| 25 | +## Implementation process |
| 26 | + |
| 27 | +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. |
| 28 | + |
| 29 | +1. Provide a data structure that represents segmentation results |
| 30 | + |
| 31 | +Open file fastdeploy/vision/common/result.h, which defines data structures for different types of model prediction results, find SegmentationResult, and use C# structure to represent the following data structure |
| 32 | + |
| 33 | +```c++ |
| 34 | +struct FASTDEPLOY_DECL SegmentationResult : public BaseResult { |
| 35 | + std::vector<uint8_t> label_map; |
| 36 | + std::vector<float> score_map; |
| 37 | + std::vector<int64_t> shape; |
| 38 | + bool contain_score_map = false; |
| 39 | + ResultType type = ResultType::SEGMENTATION; |
| 40 | +} |
| 41 | +``` |
| 42 | +
|
| 43 | +Define C# SegmentationResult structure in csharp/fastdeploy/vision/result.cs |
| 44 | +
|
| 45 | +```c# |
| 46 | +public class SegmentationResult{ |
| 47 | + public List<byte> label_map; |
| 48 | + public List<float> score_map; |
| 49 | + public List<long> shape; |
| 50 | + public bool contain_score_map; |
| 51 | + public ResultType type; |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +This structure is used by users in C# API, but in order to use it when calling C interface, we need to use C# to define corresponding structure defined in C as internal use, and C# structure defined in csharp/fastdeploy/types_internal_c.cs that maps with structure in C language. For example, define FD_SegmentationResult structure as follows |
| 56 | + |
| 57 | +```c# |
| 58 | +[StructLayout(LayoutKind.Sequential)] |
| 59 | +public struct FD_SegmentationResult { |
| 60 | + public FD_OneDimArrayUint8 label_map; |
| 61 | + public FD_OneDimArrayFloat score_map; |
| 62 | + public FD_OneDimArrayInt64 shape; |
| 63 | + [MarshalAs(UnmanagedType.U1)] |
| 64 | + public bool contain_score_map; |
| 65 | + public FD_ResultType type; |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +Next, we need to define two functions that are responsible for converting between the SegmentationResult and FD_SegmentationResult structures. These two functions need to be defined in the ConvertResult class. |
| 70 | + |
| 71 | +```c# |
| 72 | +public class ConvertResult { |
| 73 | + public static SegmentationResult |
| 74 | + ConvertCResultToSegmentationResult(FD_SegmentationResult fd_segmentation_result); |
| 75 | + public static FD_SegmentationResult |
| 76 | + ConvertSegmentationResultToCResult(SegmentationResult segmentation_result); |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +2. Provide C# API for model interface |
| 81 | + |
| 82 | +Open the file fastdeploy/vision/segmentation/ppseg/model.h, which defines the C++ interface for the segmentation model, namely fastdeploy::vision::segmentation::PaddleSegModel class. Define a class in C# to implement these interfaces. |
| 83 | +Generally, there are two parts in the C# class declaration. The first part is the interface for users, and the second part is the declaration of C interfaces to be called. |
| 84 | + |
| 85 | +```c# |
| 86 | +public class PaddleSegModel { |
| 87 | + |
| 88 | + public PaddleSegModel(string model_file, string params_file, |
| 89 | + string config_file, RuntimeOption custom_option = null, |
| 90 | + ModelFormat model_format = ModelFormat.PADDLE); |
| 91 | + ~PaddleSegModel(); |
| 92 | + |
| 93 | + public string ModelName(); |
| 94 | + |
| 95 | + public SegmentationResult Predict(Mat img); |
| 96 | + |
| 97 | + public List<SegmentationResult> BatchPredict(List<Mat> imgs); |
| 98 | + |
| 99 | + public bool Initialized(); |
| 100 | + |
| 101 | + // below are underlying C api |
| 102 | + private IntPtr fd_paddleseg_model_wrapper; |
| 103 | + [DllImport("fastdeploy.dll", |
| 104 | + EntryPoint = "FD_C_CreatePaddleSegModelWrapper")] |
| 105 | + private static extern IntPtr FD_C_CreatePaddleSegModelWrapper( |
| 106 | + string model_file, string params_file, string config_file, |
| 107 | + IntPtr fd_runtime_option_wrapper, ModelFormat model_format); |
| 108 | + [DllImport("fastdeploy.dll", |
| 109 | + EntryPoint = "FD_C_DestroyPaddleSegModelWrapper")] |
| 110 | + private static extern void |
| 111 | + FD_C_DestroyPaddleSegModelWrapper(IntPtr fd_paddleseg_model_wrapper); |
| 112 | + [DllImport("fastdeploy.dll", |
| 113 | + EntryPoint = "FD_C_PaddleSegModelWrapperPredict")] |
| 114 | + private static extern bool |
| 115 | + FD_C_PaddleSegModelWrapperPredict(IntPtr fd_paddleseg_model_wrapper, |
| 116 | + IntPtr img, |
| 117 | + ref FD_SegmentationResult fd_segmentation_result); |
| 118 | + |
| 119 | + [DllImport("fastdeploy.dll", EntryPoint = "FD_C_DestroySegmentationResult")] |
| 120 | + private static extern void |
| 121 | + FD_C_DestroySegmentationResult(ref FD_SegmentationResult fd_segmentation_result); |
| 122 | + |
| 123 | + [DllImport("fastdeploy.dll", |
| 124 | + EntryPoint = "FD_C_PaddleSegModelWrapperInitialized")] |
| 125 | + private static extern bool |
| 126 | + FD_C_PaddleSegModelWrapperInitialized(IntPtr fd_paddleseg_model_wrapper); |
| 127 | + [DllImport("fastdeploy.dll", |
| 128 | + EntryPoint = "FD_C_PaddleSegModelWrapperBatchPredict")] |
| 129 | + private static extern bool |
| 130 | + FD_C_PaddleSegModelWrapperBatchPredict(IntPtr fd_paddleseg_model_wrapper, |
| 131 | + ref FD_OneDimMat imgs, |
| 132 | + ref FD_OneDimSegmentationResult results); |
| 133 | + |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +For more details, please refer to file 'csharp/fastdeploy/vision/segmentation/model.cs'. |
| 138 | + |
| 139 | +3. Provide C# API for visualization function |
| 140 | + |
| 141 | +Open the file fastdeploy/vision/visualize/visualize.h, which has functions for visualizing inference results of different types of models. Here, we write a C# API to visualize SegmentationResult in the Visualize class. Similarly, it will call the underlying C interface to implement specific functions, so you need to declare corresponding C interfaces. |
| 142 | + |
| 143 | +```c# |
| 144 | +public class Visualize { |
| 145 | + public static Mat VisSegmentation(Mat im, |
| 146 | + SegmentationResult segmentation_result, |
| 147 | + float weight = 0.5); |
| 148 | + |
| 149 | + [DllImport("fastdeploy.dll", EntryPoint = "FD_C_VisSegmentation")] |
| 150 | + private static extern IntPtr |
| 151 | + FD_C_VisSegmentation(IntPtr im, ref FD_SegmentationResult fd_segmentation_result, float weight); |
| 152 | +} |
| 153 | +``` |
| 154 | + |
| 155 | +4. Create example to test added C# API |
| 156 | + |
| 157 | +In examples directory, according to category of model, create new directory named csharp in corresponding folder.Create csharp sample code and CMakeLists.txt inside, then compile and test it, to ensure that the added C# API can work normally. |
0 commit comments