1# API Development<a name="EN-US_TOPIC_0000001096100171"></a> 2 3- [Rule: Encapsulate the external APIs provided by the client based on the algorithm call sequence. For the SDK of an asynchronous plug-in, implement the IClientCb callback API provided by the client.](#section15872017171616) 4- [Rule: Save all common data related to client interaction in the SDK during API implementation.](#section011283741612) 5- [Recommendation: Enable the SDK to implement the IServiceDeadCb API defined by the client.](#section1199125331613) 6- [Rule: Convert dedicated algorithm data into common data of the AI engine if the SDK and plug-ins need to use the codec module.](#section93139389171) 7- [Rule: Release the memory used by the encoded or decoded parameters in the SDK. Otherwise, a memory leakage occurs.](#section1698441814183) 8- [Rule: Enable plug-ins to implement the IPlugin API defined by the server and use the PLUGIN\_INTERFACE\_IMPL statement to provide the function pointer for external systems.](#section20850717196) 9- [Rule: Use the unified data channel provided by the AI engine for plug-ins.](#section1493821732019) 10 11## Rule: Encapsulate the external APIs provided by the client based on the algorithm call sequence. For the SDK of an asynchronous plug-in, implement the **IClientCb** callback API provided by the client.<a name="section15872017171616"></a> 12 13The external APIs provided by the client of the AI engine include **AieClientInit**, **AieClientPrepare**, **AieClientSyncProcess**, **AieClientAsyncProcess**, **AieClientRelease**, **AieClientDestroy**, **AieClientSetOption**, and **AieClientGetOption**. The SDK needs to encapsulate at least the following five APIs in sequence: **AieClientInit**, **AieClientPrepare**, **AieClientSyncProcess** \(or **AieClientAsyncProcess**\), **AieClientRelease**, and **AieClientDestroy**. Otherwise, a call failure or memory leakage may occur. For example, if the **AieClientprepare** API is omitted during encapsulation, the server cannot load the plug-in. As a result, APIs that follow it cannot be called. 14 15For an asynchronous plug-in, the SDK needs to implement the **IClientCb** API to receive the algorithm inference result from the client and return the result to the third-party caller. 16 17## Rule: Save all common data related to client interaction in the SDK during API implementation.<a name="section011283741612"></a> 18 19The client of the AI engine uses the singleton pattern for API implementation. If the client is connecting to multiple SDKs, each SDK needs to store all common data exchanged with the client so that they can connect to the server to perform operations such as task inference and return the result. Common data usually includes **clientInfo**, **algorithmInfo**, and **configInfo**, which are defined in the SDK's member variables. 20 21## Recommendation: Enable the SDK to implement the **IServiceDeadCb** API defined by the client.<a name="section1199125331613"></a> 22 23The processes running on the server are system resident processes. The server provides services for clients by way of system capabilities. The **IServiceDeadCb** API is called if a server process is abnormally killed. The SDK can implement related operations in this API, for example, stopping process call or restarting the server. 24 25The following is an example of **IServiceDeadCb** API implementation: 26 27``` 28class ServiceDeadCb : public IServiceDeadCb { 29public: 30ServiceDeadCb() = default; 31~ServiceDeadCb() override = default; 32void OnServiceDead() override 33{ 34printf("[ServiceDeadCb]OnServiceDead Callback happens"); 35} 36}; 37``` 38 39As shown above, the SDK can implement its own operations in the **OnServiceDead\(\)** function, for example, stopping API call. 40 41## Rule: Convert dedicated algorithm data into common data of the AI engine if the SDK and plug-ins need to use the codec module.<a name="section93139389171"></a> 42 43For plug-ins, inference data is transmitted by the third-party caller to them through the client and server. The required data type varies according to algorithms. For example, the CV algorithm requires image data, and the ASR algorithm requires audio data. To address this issue, the AI engine provides the codec capabilities to convert different types of data into common data that can be used by it. 44 45The encoded data is as follows: 46 47``` 48struct DataInfo { 49unsigned char *data; 50int length; 51} DataInfo; 52 53``` 54 55As shown above, **DataInfo** consists of two variables: a pointer to the data memory, and the data length. 56 57To use the APIs of the AI engine framework, you need to: 58 591. Add the dependency header file **utils/encdec/include/encdec.h**. 60 612. Add the dependency items in the **build.gn** file. 62 63Add **"//foundation/ai/engine/services/common"** to **include\_dirs**. 64 65Add **"//foundation/ai/engine/services/common/utils/encdec:encdec"** to **deps**. 66 673. Convert different types of data through codec. The following is an example: 68 69``` 70// Example function for encoding: arg1, arg2, and arg3 are variables to be encoded, and dataInfo is the encoding result. 71retCode = ProcessEncode(dataInfo, arg1, arg2, arg3) // The number of parameters can be flexible. 72// Example function for decoding: dataInfo is the data to be decoded, and arg1, arg2, and arg3 are the decoding result. 73retCode = ProcessDecode(dataInfo, arg1, arg2, arg3) // The number of parameters can be flexible. 74``` 75 76Note: 77 78- The sequence of parameters must be the same during encoding and decoding. 79- After encoding, the memory used by **dataInfo** needs to be manually released by the caller. 80- The memory is managed and released separately on the server and the client. 81- If a pointer contains the shared memory, no extra processing is required. 82- If other types of pointers are used, you need to dereference them before using **ProcessEncode** or **ProcessDecode**. 83- The codec module has not been adapted to the **class** data type and therefore it is not recommended. 84 85## Rule: Release the memory used by the encoded or decoded parameters in the SDK. Otherwise, a memory leakage occurs.<a name="section1698441814183"></a> 86 87Encoding is essentially a process of encapsulating different types of data in the same memory space and then encapsulating the start address and length of the memory into the body. The plug-in is unable to release the memory that has been allocated to output parameter data returned to the SDK through encoding. To obtain the data, the SDK first needs to release the memory. 88 89The following is an example of releasing the memory: 90 91``` 92DataInfo outputInfo = { 93.data = nullptr, 94.length = 0, 95}; 96AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); 97if (outputInfo.data != nullptr) { 98free(outputInfo.data); 99outputInfo.data = nullptr; 100outputInfo.length = 0; 101} 102``` 103 104## Rule: Enable plug-ins to implement the **IPlugin** API defined by the server and use the **PLUGIN\_INTERFACE\_IMPL** statement to provide the function pointer for external systems.<a name="section20850717196"></a> 105 106The server manages a variety of plug-ins, and the API implementation logic varies according to plug-ins. To unify the plug-in loading process, the AI engine provides the **IPlugin** API. In the runtime environment, a plug-in is loaded as a dynamic link library \(DLL\) by the AI engine framework in dlopen mode. Therefore, the plug-in needs to use the **PLUGIN\_INTERFACE\_IMPL** statement to expose the function pointer. Otherwise, the plug-in cannot be properly loaded. 107 108## Rule: Use the unified data channel provided by the AI engine for plug-ins.<a name="section1493821732019"></a> 109 110The AI engine provides a unified data channel between the server and plug-ins to send inference requests from the SDK and returned results from plug-ins. Plug-ins need to obtain the request data and encapsulate the inference result over the data channel when calling the inference API. 111 112The following is an example of using the data channel: 113 114``` 115int SyncProcess(IRequest *request, IResponse *&response) 116{ 117HILOGI("[IvpPlugin]Begin SyncProcess"); 118if (request == nullptr) { 119HILOGE("[IvpPlugin]SyncProcess request is nullptr"); 120return RETCODE_NULL_PARAM; 121} 122DataInfo inputInfo = request->GetMsg(); 123if (inputInfo.data == nullptr) { 124HILOGE("[IvpPlugin]InputInfo data is nullptr"); 125return RETCODE_NULL_PARAM; 126} 127 128... 129 130response = IResponse::Create(request); 131response->SetResult(outputInfo); 132return RETCODE_SUCCESS; 133} 134``` 135 136In the example, the request and response are the data body sent over the data channel. The server encapsulates data in the request and sends it to the plug-in. After completing algorithm processing, the plug-in encapsulates the result into the response and returns it to the server over the data channel. 137 138