• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# IDL Specifications and User Guide (for System Applications Only)
2
3## IDL Overview
4To ensure successful communications between the client and server, interfaces recognized by both parties must be defined. The OpenHarmony Interface Definition Language (IDL) is a tool for defining such interfaces. IDL decomposes objects into primitives that can be understood by the operating system and encapsulates cross-boundary objects based on your requirements.
5
6**Figure 1** IDL interface description
7
8![IDL-interface-description](./figures/IDL-interface-description.png)
9
10**IDL provides the following functions:**
11
12- Declares interfaces provided by system services for external systems, and based on the interface declaration, generates C, C++, JS, or TS code for inter-process communication (IPC) or remote procedure call (RPC) proxies and stubs during compilation.
13
14- Declares interfaces provided by abilities for external systems, and based on the interface declaration, generates C, C++, JS, or TS code for IPC or RPC proxies and stubs during compilation.
15
16**Figure 2** IPC/RPC communication model
17
18![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png)
19
20**IDL has the following advantages:**
21
22- Services are defined in the form of interfaces in IDL. Therefore, you do not need to focus on implementation details.
23
24- Interfaces defined by IDL can be used in IPC or RPC scenarios. The information or code generated based on the definitions in IDL simplifies IPC or RPC implementation.
25
26## IDL File Structure
27
28### Data Types
29
30#### Primitive Type
31| IDL Primitive Type| C++ Primitive Type| TS Primitive Type|
32|   --------    |  --------     | --------     |
33|void           | void          | void         |
34|boolean        | bool          | boolean      |
35|byte           | int8_t        | number       |
36|short          | int16_t       | number       |
37|int            | int32_t       | number       |
38|long           | int64_t       | number       |
39|float          | float         | number       |
40|double         | double        | number       |
41|String         | std::string   | string       |
42
43The preceding table lists the primitive types supported by IDL and the mappings to the C++ and TS primitive types.
44
45#### sequenceable Type
46The sequenceable type is declared using the keyword **sequenceable**. This type can be passed during IPC or RPC through **Parcel** objects. The declaration mode of the sequenceable type in C++ is different from that in TS.
47
48In C++, the declaration is placed in the file header in the format of **sequenceable includedir..namespace.typename**.  It can be in any of the following forms:
49
50```cpp
51sequenceable includedir..namespace.typename
52sequenceable includedir...typename
53sequenceable namespace.typename
54```
55
56In the preceding information, **includedir** indicates the directory where the header file of the type is located, and the dot (.) is used as the separator. **namespace** indicates the namespace where the type is located, and the dot (.) is used as the separator. **typename** indicates the data type, which can contain only English characters. **includedir** and **namespace** are separated by two dots (..). If the declaration statement does not contain two dots, all characters except the last typename will be parsed as a namespace. Example:
57
58```cpp
59sequenceable a.b..C.D
60```
61
62The preceding statement is parsed into the following code in the C++ header file:
63
64```cpp
65#include "a/b/d.h"
66using C::D;
67```
68
69In TS, the declaration is placed in the file header in the format of **sequenceable namespace.typename;**. An example is provided below, where **idl** is the namespace and **MySequenceable** is the type name:
70
71```ts
72sequenceable idl.MySequenceable
73```
74
75In the preceding information, **namespace** indicates the namespace to which the data type belongs, **typename** indicates the data type name, and **MySequenceable** indicates that data can be passed during IPC using **Parcel** objects. The sequenceable type is not defined in the IDL file, but in the .ts file. Therefore, IDL adds the following statement to the generated .ts file based on the declaration:
76
77```ts
78import MySequenceable from "./my_sequenceable"
79```
80
81Note that IDL does not implement code for this type. It only imports the header file in the specified format or imports the specified module and uses the type. Therefore, you must ensure that the imported directory, namespace, and type are correct.
82
83#### Interface Type
84The interface type refers to interfaces defined in IDL files. The interfaces defined in an IDL file can be directly used as the parameter type or return value type of a method declared in the file. If an IDL file attempts to use interfaces defined in other IDL files, forward declaration must be contained in the header of that IDL file.
85
86The declaration form in C++ is similar to that of the sequenceable type. The declaration form is as follows:
87
88```cpp
89interface includedir..namespace.typename
90```
91
92In TS, the declaration form is as follows:
93
94```ts
95interface namespace.interfacename
96```
97
98In the preceding information, **namespace** indicates the namespace to which the interface belongs, and **interfacename** indicates the name of the interface. For example, **interface OHOS.IIdlTestObserver;** declares the **IIdlTestObserver** interface defined in another IDL file. This interface can be used as the parameter type or return value type of a method in the current file. IDL adds the following statement to the generated .ts file based on the statement:
99
100```ts
101import IIdlTestObserver from "./i_idl_test_observer"
102```
103
104#### Array Type
105The array type is represented by T[], where **T** can be the primitive, sequenceable, interface, or array type. In C++, this type is generated as **std::vector<T>**.
106The table below lists the mappings between the IDL array type and TS and C++ data types.
107
108|IDL Data Type | C++ Data Type          | TS Data Type    |
109|   -------              |  --------            |  --------    |
110|T[]                     | std::vector<T> | T[]          |
111
112#### Container Type
113IDL supports two container types: List and Map. The List container is represented in the format of **List&lt;T&gt;**. The Map container is represented in the format of **Map<KT,VT>**, where **T**, **KT**, and **VT** can be of the primitive, sequenceable, interface, array, or container type.
114
115In C++, the List container type is generated as **std::list**, and the Map container type is generated as **std::map**.
116
117In TS, the List container type is not supported, and the Map container type is generated as **Map**.
118
119The table below lists the mappings between the IDL container type and TS and C++ data types.
120
121|IDL Data Type | C++ Data Type      | TS Data Type    |
122|   --------             |  --------        |  -------     |
123|List&lt;T&gt;           | std::list        | Not supported       |
124|Map<KT,VT>              | std::map         | Map          |
125
126
127### Specifications for Compiling IDL Files
128Only one interface type can be defined in an IDL file, and the interface name must be the same as the file name. The interface definition of the IDL file is described in Backus-Naur form (BNF). The basic definition format is as follows:
129
130```
131[<*interface_attr_declaration*>]interface<*interface_name_with_namespace*>{<*method_declaration*>}
132```
133
134In the preceding information, <*interface_attr_declaration*> declares interface attributes. Currently, only the **oneway** attribute is supported, indicating that all methods in the interface are unidirectional. Such a method returns value without waiting for the execution to complete. This attribute is optional. If this attribute is not set, synchronous call is used. The interface name must contain the complete interface header file directory, namespace, and method declaration. Null interfaces are not allowed.
135The method declaration format in the interface is as follows:
136
137```
138[<*method_attr_declaration*>]<*result_type*><*method_declaration*>
139```
140
141In the preceding information, <*method_attr_declaration*> describes the interface attributes. Currently, only the **oneway** attribute is supported, indicating that the method is unidirectional. Such a method returns value without waiting for the execution to complete. This attribute is optional. If this attribute is not set, synchronous call is used. <*result_type*> indicates the type of the return value, and <*method_declaration*> indicates the method name and parameter declaration.
142The parameter declaration format is as follows:
143
144```
145[<*formal_param_attr*>]<*type*><*identifier*>
146```
147
148The value of <*formal_param_attr*> can be **in**, **out**, or **inout**, indicating that the parameter is an input parameter, an output parameter, or both an input and an output parameter, respectively. A **oneway** method does not allow **output** or **inout** parameters or return values.
149
150## How to Develop
151
152### Obtaining IDL
153On DevEco Studio, choose **Tools > SDK Manager** to view the local installation path of the OpenHarmony SDK. The following figure uses DevEco Studio 3.0.0.993 as an example.
154
155![SDKpath](./figures/SDKpath.png)
156
157![SDKpath](./figures/SDKpath2.png)
158
159Go to the local installation path, choose **toolchains > 3.x.x.x** (the folder named after the version number), and check whether the executable file of IDL exists.
160
161> **NOTE**
162>
163> Use the SDK of the latest version. The use of an earlier version may cause errors in some statements.
164
165If the executable file does not exist, download the SDK package from the mirror as instructed in the [Release Notes](../../release-notes). The following uses [3.2 Beta3](../../release-notes/OpenHarmony-v3.2-beta3.md) as an example.
166
167For details about how to replace the SDK package, see [Full SDK Compilation Guide](../faqs/full-sdk-compile-guide.md).
168
169After obtaining the executable file, perform subsequent development steps based on your scenario.
170
171### Development Using TS
172
173#### Creating an IDL File
174
175You can use TS to create IDL files.
176
177 For example, create a file named **IIdlTestService.idl** with the following content:
178
179```cpp
180  interface OHOS.IIdlTestService {
181      int TestIntTransaction([in] int data);
182      void TestStringTransaction([in] String data);
183      void TestMapTransaction([in] Map<int, int> data);
184      int TestArrayTransaction([in] String[] data);
185  }
186```
187
188Run the **idl -gen-ts -d *dir* -c dir/IIdlTestService.idl** command in the folder where the executable file is located.
189
190-*dir* next to **d** is the target output folder. For example, if the target output folder is **IIdlTestServiceTs**, run the **idl -gen-ts -d IIdlTestServiceTs -c IIdlTestServiceTs/IIdlTestService.idl** command in the folder where the executable file is located. The interface file, stub file, and proxy file are generated in the *dir* directory (**IIdlTestServiceTs** directory in this example) in the execution environment.
191
192> **NOTE**
193>
194> The generated interface class file name must be the same as that of the .idl file. Otherwise, an error occurs during code generation.
195
196For example, for an .idl file named **IIdlTestService.idl** and target output directory named **IIdlTestServiceTs**, the directory structure is similar to the following:
197
198```
199├── IIdlTestServiceTs  # IDL code output folder
200│   ├── i_idl_test_service.ts  # File generated
201│   ├── idl_test_service_proxy.ts  # File generated
202│   ├── idl_test_service_stub.ts  # File generated
203│   └── IIdlTestService.idl  # Constructed .idl file
204└── idl.exe  # Executable file of IDL
205```
206
207#### Exposing Interfaces on the Server
208
209The stub class generated by IDL is an abstract implementation of the interface class and declares all methods in the IDL file.
210
211```ts
212import {testIntTransactionCallback} from "./i_idl_test_service";
213import {testStringTransactionCallback} from "./i_idl_test_service";
214import {testMapTransactionCallback} from "./i_idl_test_service";
215import {testArrayTransactionCallback} from "./i_idl_test_service";
216import IIdlTestService from "./i_idl_test_service";
217import rpc from "@ohos.rpc";
218
219export default class IdlTestServiceStub extends rpc.RemoteObject implements IIdlTestService {
220    constructor(des: string) {
221        super(des);
222    }
223
224    async onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence,
225        option: rpc.MessageOption): Promise<boolean> {
226        console.log("onRemoteMessageRequest called, code = " + code);
227        if (code == IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION) {
228            let _data = data.readInt();
229            this.testIntTransaction(_data, (errCode: number, returnValue: number) => {
230                reply.writeInt(errCode);
231                if (errCode == 0) {
232                    reply.writeInt(returnValue);
233                }
234            });
235            return true;
236        } else if (code == IdlTestServiceStub.COMMAND_TEST_STRING_TRANSACTION) {
237            let _data = data.readString();
238            this.testStringTransaction(_data, (errCode: number) => {
239                reply.writeInt(errCode);
240            });
241            return true;
242        } else if (code == IdlTestServiceStub.COMMAND_TEST_MAP_TRANSACTION) {
243            let _data: Map<number, number> = new Map();
244            let _dataSize = data.readInt();
245            for (let i = 0; i < _dataSize; ++i) {
246                let key = data.readInt();
247                let value = data.readInt();
248                _data.set(key, value);
249            }
250            this.testMapTransaction(_data, (errCode: number) => {
251                reply.writeInt(errCode);
252            });
253            return true;
254        } else if (code == IdlTestServiceStub.COMMAND_TEST_ARRAY_TRANSACTION) {
255            let _data = data.readStringArray();
256            this.testArrayTransaction(_data, (errCode: number, returnValue: number) => {
257                reply.writeInt(errCode);
258                if (errCode == 0) {
259                    reply.writeInt(returnValue);
260                }
261            });
262            return true;
263        } else {
264            console.log("invalid request code" + code);
265        }
266        return false;
267    }
268
269    testIntTransaction(data: number, callback: testIntTransactionCallback): void{}
270    testStringTransaction(data: string, callback: testStringTransactionCallback): void{}
271    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void{}
272    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void{}
273
274    static readonly COMMAND_TEST_INT_TRANSACTION = 1;
275    static readonly COMMAND_TEST_STRING_TRANSACTION = 2;
276    static readonly COMMAND_TEST_MAP_TRANSACTION = 3;
277    static readonly COMMAND_TEST_ARRAY_TRANSACTION = 4;
278}
279```
280
281You need to inherit the interface class defined in the IDL file and implement the methods in the class. The following code snippet shows how to inherit the **IdlTestServiceStub** interface class and implement the **testIntTransaction**, **testStringTransaction**, **testMapTransaction**, and **testArrayTransaction** methods.
282
283```ts
284import {testIntTransactionCallback} from "./i_idl_test_service"
285import {testStringTransactionCallback} from "./i_idl_test_service"
286import {testMapTransactionCallback} from "./i_idl_test_service";
287import {testArrayTransactionCallback} from "./i_idl_test_service";
288import IdlTestServiceStub from "./idl_test_service_stub"
289
290
291class IdlTestImp extends IdlTestServiceStub {
292
293    testIntTransaction(data: number, callback: testIntTransactionCallback): void
294    {
295        callback(0, data + 1);
296    }
297    testStringTransaction(data: string, callback: testStringTransactionCallback): void
298    {
299        callback(0);
300    }
301    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void
302    {
303        callback(0);
304    }
305    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void
306    {
307        callback(0, 1);
308    }
309}
310```
311
312After the service implements the interface, the interface needs to be exposed to the client for connection. If your service needs to expose this interface, extend **Ability** and implement **onConnect()** to return **IRemoteObject** so that the client can interact with the service process. The following code snippet shows how to expose the **IRemoteAbility** interface to the client:
313
314```ts
315import Want from '@ohos.app.ability.Want';
316import rpc from "@ohos.rpc";
317
318class ServiceAbility {
319  onStart() {
320    console.info('ServiceAbility onStart');
321  }
322  onStop() {
323    console.info('ServiceAbility onStop');
324  }
325  onCommand(want: Want, startId: number) {
326    console.info('ServiceAbility onCommand');
327  }
328  onConnect(want: Want) {
329    console.info('ServiceAbility onConnect');
330    try {
331      console.log('ServiceAbility want:' + typeof(want));
332      console.log('ServiceAbility want:' + JSON.stringify(want));
333      console.log('ServiceAbility want name:' + want.bundleName)
334    } catch(err) {
335      console.log('ServiceAbility error:' + err)
336    }
337    console.info('ServiceAbility onConnect end');
338    return new IdlTestImp('connect') as rpc.RemoteObject;
339  }
340  onDisconnect(want: Want) {
341    console.info('ServiceAbility onDisconnect');
342    console.info('ServiceAbility want:' + JSON.stringify(want));
343  }
344}
345
346export default new ServiceAbility()
347```
348
349#### Calling Methods from the Client for IPC
350
351When the client calls **connectServiceExtensionAbility()** to connect to a ServiceAbility, the **onConnect** callback in **onAbilityConnectDone** of the client receives the **IRemoteObject** instance returned by the **onConnect()** method of the ServiceAbility. The client and ServiceAbility are in different applications. Therefore, the directory of the client application must contain a copy of the .idl file (the SDK automatically generates the proxy class). The **onConnect** callback then uses the **IRemoteObject** instance to create the **testProxy** instance of the **IdlTestServiceProxy** class and calls the related IPC method. The sample code is as follows:
352
353```ts
354import common from '@ohos.app.ability.common';
355import Want from '@ohos.app.ability.Want';
356import IdlTestServiceProxy from './idl_test_service_proxy'
357
358function callbackTestIntTransaction(result: number, ret: number): void {
359  if (result == 0 && ret == 124) {
360    console.log('case 1 success');
361  }
362}
363
364function callbackTestStringTransaction(result: number): void {
365  if (result == 0) {
366    console.log('case 2 success');
367  }
368}
369
370function callbackTestMapTransaction(result: number): void {
371  if (result == 0) {
372    console.log('case 3 success');
373  }
374}
375
376function callbackTestArrayTransaction(result: number, ret: number): void {
377  if (result == 0 && ret == 124) {
378    console.log('case 4 success');
379  }
380}
381
382let onAbilityConnectDone: common.ConnectOptions = {
383  onConnect: (elementName, proxy) => {
384    let testProxy: IdlTestServiceProxy = new IdlTestServiceProxy(proxy);
385    let testMap: Map<number, number> = new Map();
386    testMap.set(1, 1);
387    testMap.set(1, 2);
388    testProxy.testIntTransaction(123, callbackTestIntTransaction);
389    testProxy.testStringTransaction('hello', callbackTestStringTransaction);
390    testProxy.testMapTransaction(testMap, callbackTestMapTransaction);
391    testProxy.testArrayTransaction(['1','2'], callbackTestMapTransaction);
392  },
393  onDisconnect: (elementName) => {
394    console.log('onDisconnectService onDisconnect');
395  },
396  onFailed: (code) => {
397    console.log('onDisconnectService onFailed');
398  }
399};
400
401let context: common.UIAbilityContext = this.context;
402
403function connectAbility(): void {
404    let want: Want = {
405        bundleName: 'com.example.myapplicationidl',
406        abilityName: 'com.example.myapplicationidl.ServiceAbility'
407    };
408    let connectionId = -1;
409    connectionId = context.connectServiceExtensionAbility(want, onAbilityConnectDone);
410}
411
412
413```
414
415#### Transferring a sequenceable Object During IPC
416
417You can send a class from one process to another through IPC interfaces. However, you must ensure that the peer can use the code of this class and this class supports the **marshalling** and **unmarshalling** methods. The system uses **marshalling** and **unmarshalling** to serialize and deserialize objects into objects that can be identified by each process.
418
419**To create a class that supports the sequenceable type, perform the following operations:**
420
4211. Implement the **marshalling** method, which obtains the current state of the object and serializes the object into a **Parcel** object.
4222. Implement the **unmarshalling** method, which deserializes the object from a **Parcel** object.
423
424The following is an example of the **MySequenceable** class code:
425
426```ts
427import rpc from '@ohos.rpc';
428export default class MySequenceable implements rpc.Sequenceable {
429    constructor(num: number, str: string) {
430        this.num = num;
431        this.str = str;
432    }
433    getNum() : number {
434        return this.num;
435    }
436    getString() : string {
437        return this.str;
438    }
439    marshalling(messageParcel: rpc.MessageParcel) {
440        messageParcel.writeInt(this.num);
441        messageParcel.writeString(this.str);
442        return true;
443    }
444    unmarshalling(messageParcel: rpc.MessageParcel) {
445        this.num = messageParcel.readInt();
446        this.str = messageParcel.readString();
447        return true;
448    }
449    private num: number;
450    private str: string;
451}
452```
453
454### Development Using C++ (Automatically Generating ServiceAbility Interface Template Code During Compilation)
455
456#### Creating an IDL File
457
458You can use C++ to create IDL files.
459
460For example, create a file named **IQuickFixManager.idl** with the following content:
461
462```
463/*
464 * Copyright (c) 2023 Huawei Device Co., Ltd.
465 * Licensed under the Apache License, Version 2.0 (the "License");
466 * you may not use this file except in compliance with the License.
467 * You may obtain a copy of the License at
468 *
469 *     http://www.apache.org/licenses/LICENSE-2.0
470 *
471 * Unless required by applicable law or agreed to in writing, software
472 * distributed under the License is distributed on an "AS IS" BASIS,
473 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
474 * See the License for the specific language governing permissions and
475 * limitations under the License.
476 */
477
478sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo;
479interface OHOS.AAFwk.IQuickFixManager {
480    void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
481    void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
482    void RevokeQuickFix([in] String bundleName);
483}
484```
485
486#### Modifying the BUILD.gn File
487
4881. Import the IDL tool template to the current **BUILD.gn** file.
489
490   ```bash
491   # Copy the line below to the .gn file.
492   import("//foundation/ability/idl_tool/idl_config.gni")
493   ```
494
4952. Invoke the IDL tool to generate a C++ template file.
496
497   Replace *axx_bxx_cxx* in the code below with the .cpp file names of the generated stub and proxy.
498
499   ```bash
500   idl_interface_sources = [
501     # Change axx_bxx_cxx to the name of the .cpp file of the generated proxy.
502     "${target_gen_dir}/axx_bxx_cxx_proxy.cpp",
503     # Change axx_bxx_cxx to the name of the .cpp file of the generated stub.
504     "${target_gen_dir}/axx_bxx_cxx_stub.cpp",
505   ]
506
507   # Use idl_gen_interface to generate a template file. You need to enter the parameter name, which will be used in deps.
508   idl_gen_interface("EEEFFFGGG") {
509     # Name of your .idl file, which is in the same path as the .gn file.
510     src_idl = rebase_path("IAxxBxxCxx.idl")
511     # The template file .cpp of the proxy and stub. You can copy the line below to the .gn file.
512     dst_file = string_join(",", idl_interface_sources)
513     # Enable hitrace. The value is the uint64_t type identifier defined in the hitrace_meter.h file. You need to enter the variable name of the constant.
514     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
515     # Enable hilog. The domain ID is a hexadecimal integer.
516     log_domainid = "0xD003900"
517     # Enable hilog. The tag name is a string, which is generally a subsystem name.
518     log_tag = "QuickFixManagerService"
519   }
520   ```
521
522   The names of ***axx_bxx_cxx_*proxy.cpp** and ***axx_bxx_cxx_*stub.cpp** are the same as the corresponding .idl file names in lowercase, with an underscore (_) added for each CamelCase segment.
523
524   ```bash
525   # For example, if the .idl file is IQuickFixManager.idl,
526   then axx_bxx_cxx_proxy.cpp is quick_fix_manager_proxy.cpp
527   and axx_bxx_cxx_stub.cpp is quick_fix_manager_stub.cpp.
528   ```
529
530   If the name of the template file to be generated starts with I, add one **I** before the interface name.
531
532   ```bash
533   # For example, if the generated template file is **quick_fix_manager_proxy.cpp**, the interface name is **IQuickFixManager**.
534   # Definition in the .idl file
535   interface OHOS.AAFwk.IQuickFixManager {
536       void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
537       void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
538       void RevokeQuickFix([in] String bundleName);
539   }
540   ```
541
542   Configure hilog. The log_domainid and log_tag parameters must appear in pairs; otherwise, a compilation error occurs.
543
544   ```bash
545   idl_gen_interface("quickfix_manager_interface") {
546     src_idl = rebase_path("IQuickFixManager.idl")
547     dst_file = string_join(",", idl_interface_sources)
548     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
549     log_domainid = "0xD003900"
550     log_tag = "QuickFixManagerService" # An error occurs during compilation if only log_tag or log_domainid is included.
551   }
552   ```
553
5543. Add the header file path of the template file to **BUILD.gn**.
555
556   You only need to add **${target_gen_dir}** to **include_dirs**.
557
558   ```bash
559   include_dirs = [
560     "aaa/bbb/ccc",        # Path of the original header file
561     "${target_gen_dir}",  # Path of the template header file
562   ]
563   ```
564
5654. Add the path of the template file .cpp to **BUILD.gn**.
566
567   If **sources** contain ***axx_bxx_cxx_*proxy.cpp** and ***axx_bxx_cxx_*stub.cpp**, delete them and add **sources += filter_include(output_values, [ "*.cpp" ])**.
568
569   ```bash
570   output_values = get_target_outputs(":EEEFFFGGG") # Return the output file list of the target tag. Replace EEEFFFGGG.
571   sources = [ "axx_bxx_cxx_proxy.cpp" ] # Delete axx_bxx_cxx_proxy.cpp.
572   sources += filter_include(output_values, [ "*.cpp" ]) # filter_include selects the list that meets the requirements. You can copy this line directly.
573   ```
574
5755. Add the dependency **EEEFFFGGG** to **BUILD.gn**.
576
577   ```bash
578   deps = [
579       ":EEEFFFGGG",
580     ]
581   ```
582
583   The name of the dependency added to **deps** must be the same as the parameter name of the **idl_gen_interface** function.
584
585   ```bash
586   idl_gen_interface("quickfix_manager_interface") {
587     src_idl = rebase_path("IQuickFixManager.idl")
588     dst_file = string_join(",", idl_interface_sources)
589     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
590     log_domainid = "0xD003900"
591     log_tag = "QuickFixManagerService"
592   }
593   deps = [
594    "${ability_runtime_innerkits_path}/app_manager:app_manager",
595    ":quickfix_manager_interface"] # Same as the parameter name of the idl_gen_interface function.
596   ```
597
5986. Add external dependencies of the template file to **BUILD.gn**.
599
600   Add the external dependencies of the template file to **external_deps**.
601
602   If a dependency already exists, you do not need to add it again; otherwise, compilation errors may occur.
603
604   ```bash
605     external_deps = [
606     # Mandatory dependency of the template file
607     "c_utils:utils",
608     # Mandatory dependency of the hilog output
609     "hilog:libhilog",
610     # Mandatory dependency of the hitrace output
611     "hitrace:hitrace_meter",
612     # Mandatory dependency of the template file
613     "ipc:ipc_core",
614   ]
615   ```
616
617#### Example
618
619The following uses the quick fix service as an example:
620
6211. Create the **IQuickFixManager.idl** file.
622
623   When creating the .idl file, ensure that the interface name is the same as the .idl file name; otherwise, an error occurs during code generation.
624
625   The path of the .idl file must be the same as that of the **BUILD.gn** file of the function code.
626
627   In the example, the file is in **foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/**.
628
629   ```bash
630   /*
631    * Copyright (c) 2023 Huawei Device Co., Ltd.
632    * Licensed under the Apache License, Version 2.0 (the "License");
633    * you may not use this file except in compliance with the License.
634    * You may obtain a copy of the License at
635    *
636    *     http://www.apache.org/licenses/LICENSE-2.0
637    *
638    * Unless required by applicable law or agreed to in writing, software
639    * distributed under the License is distributed on an "AS IS" BASIS,
640    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
641    * See the License for the specific language governing permissions and
642    * limitations under the License.
643    */
644
645   sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo;
646   interface OHOS.AAFwk.IQuickFixManager {
647       void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
648       void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
649       void RevokeQuickFix([in] String bundleName);
650   }
651   ```
652
653   When creating the .idl file, change the return value of the function from int to void.
654
655   ```bash
656   # Functions in quick_fix_manager_client.h
657       int32_t ApplyQuickFix(const std::vector<std::string> &quickFixFiles);
658       int32_t GetApplyedQuickFixInfo(const std::string &bundleName, ApplicationQuickFixInfo &quickFixInfo);
659       int32_t RevokeQuickFix(const std::string &bundleName);
660   # Definition in the .idl file
661   interface OHOS.AAFwk.QuickFixManager {
662       void ApplyQuickFix([in] String[] quickFixFiles);
663       void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
664       void RevokeQuickFix([in] String bundleName);
665   }
666   ```
667
6682. Modify the BUILD.gn file.
669
670   ```bash
671   # Copyright (c) 2023 Huawei Device Co., Ltd.
672   # Licensed under the Apache License, Version 2.0 (the "License");
673   # you may not use this file except in compliance with the License.
674   # You may obtain a copy of the License at
675   #
676   #     http://www.apache.org/licenses/LICENSE-2.0
677   #
678   # Unless required by applicable law or agreed to in writing, software
679   # distributed under the License is distributed on an "AS IS" BASIS,
680   # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
681   # See the License for the specific language governing permissions and
682   # limitations under the License.
683
684   import("//build/ohos.gni")
685   import("//foundation/ability/ability_runtime/ability_runtime.gni")
686   import("//foundation/ability/idl_tool/idl_config.gni")
687
688   idl_interface_sources = [
689     "${target_gen_dir}/quick_fix_manager_proxy.cpp",
690     "${target_gen_dir}/quick_fix_manager_stub.cpp",
691   ]
692
693   idl_gen_interface("quickfix_manager_interface") {
694     src_idl = rebase_path("IQuickFixManager.idl")
695     dst_file = string_join(",", idl_interface_sources)
696     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
697     log_domainid = "0xD003900"
698     log_tag = "QuickFixManagerService"
699   }
700
701   config("quickfix_config") {
702     visibility = [ ":*" ]
703     include_dirs = [
704       "include",
705       "${target_gen_dir}",
706     ]
707     cflags = []
708     if (target_cpu == "arm") {
709       cflags += [ "-DBINDER_IPC_32BIT" ]
710     }
711   }
712
713   ohos_shared_library("quickfix_manager") {
714     configs = [ "${ability_runtime_services_path}/common:common_config" ]
715     public_configs = [ ":quickfix_config" ]
716
717     output_values = get_target_outputs(":quickfix_manager_interface")
718     sources = [
719       "src/quick_fix_error_utils.cpp",
720       "src/quick_fix_info.cpp",
721       "src/quick_fix_load_callback.cpp",
722       "src/quick_fix_manager_client.cpp",
723       "src/quick_fix_utils.cpp",
724     ]
725     sources += filter_include(output_values, [ "*.cpp" ])
726     defines = [ "AMS_LOG_TAG = \"QuickFixService\"" ]
727     deps = [
728       ":quickfix_manager_interface",
729       "${ability_runtime_innerkits_path}/app_manager:app_manager",
730     ]
731
732     external_deps = [
733       "ability_base:want",
734       "bundle_framework:appexecfwk_base",
735       "bundle_framework:appexecfwk_core",
736       "c_utils:utils",
737       "hilog:libhilog",
738       "hitrace:hitrace_meter",
739       "ipc:ipc_single",
740       "safwk:system_ability_fwk",
741       "samgr:samgr_proxy",
742     ]
743
744     innerapi_tags = [ "platformsdk" ]
745     subsystem_name = "ability"
746     part_name = "ability_runtime"
747   }
748   ```
749
7503. Specify the path and directory structure of the generated template file.
751
752   Take rk3568 as an example. The path of the template file generated in the instance is **out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/**,
753
754   where **foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/** is the relative path of the .idl file.
755
756   The directory structure of the template file generated is as follows:
757
758   ```bash
759   |-- out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/
760      |-- iquick_fix_manager.h
761      |-- quick_fix_manager_stub.h
762      |-- quick_fix_manager_stub.cpp
763      |-- quick_fix_manager_proxy.h
764      |-- quick_fix_manager_proxy.cpp
765   ```
766
767