1e41f4b71Sopenharmony_ci# OpenHarmony IDL工具规格及使用说明书(仅对系统应用开放)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## IDL接口描述语言简介
4e41f4b71Sopenharmony_ci当客户端和服务器进行IPC通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony IDL(OpenHarmony Interface Definition Language)则是一种定义此类接口的工具。OpenHarmony IDL先把需要传递的对象分解成操作系统能够理解的基本类型,并根据开发者的需要封装跨边界的对象。
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci  **图1** IDL接口描述
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ci![IDL-interface-description](./figures/IDL-interface-description.png)
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci **OpenHarmony IDL接口描述语言主要用于:** 
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci- 声明系统服务对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci- 声明Ability对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci**图2** IPC/RPC通信模型
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png)
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci **使用OpenHarmony IDL接口描述语言声明接口具有以下优点:** 
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci- OpenHarmony IDL中是以接口的形式定义服务,可以专注于定义而隐藏实现细节。
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci- OpenHarmony IDL中定义的接口可以支持跨进程调用或跨设备调用。根据OpenHarmony IDL中的定义生成的信息或代码可以简化跨进程或跨设备调用接口的实现。
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci## IDL接口描述语言构成
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci### 数据类型
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci#### 基础数据类型
31e41f4b71Sopenharmony_ci| IDL基本数据类型 | C++基本数据类型 | TS基本数据类型 |
32e41f4b71Sopenharmony_ci|   --------    |  --------     | --------     |
33e41f4b71Sopenharmony_ci|void           | void          | void         |
34e41f4b71Sopenharmony_ci|boolean        | bool          | boolean      |
35e41f4b71Sopenharmony_ci|byte           | int8_t        | number       |
36e41f4b71Sopenharmony_ci|short          | int16_t       | number       |
37e41f4b71Sopenharmony_ci|int            | int32_t       | number       |
38e41f4b71Sopenharmony_ci|long           | int64_t       | number       |
39e41f4b71Sopenharmony_ci|float          | float         | number       |
40e41f4b71Sopenharmony_ci|double         | double        | number       |
41e41f4b71Sopenharmony_ci|String         | std::string   | string       |
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ciIDL支持的基本数据类型及其映射到C++、TS上的数据类型的对应关系如上表所示。
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci#### sequenceable数据类型
46e41f4b71Sopenharmony_cisequenceable数据类型是指使用“sequenceable”关键字声明的数据,表明该数据类型可以被序列化进行跨进程或跨设备传递。sequenceable在C++与TS中声明方式存在一定差异。
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci在C++中sequenceable数据类型的声明放在文件的头部,以“sequenceable includedir..namespace.typename”的形式声明。具体而言。声明可以有如下三个形式:
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci```cpp
51e41f4b71Sopenharmony_cisequenceable includedir..namespace.typename
52e41f4b71Sopenharmony_cisequenceable includedir...typename
53e41f4b71Sopenharmony_cisequenceable namespace.typename
54e41f4b71Sopenharmony_ci```
55e41f4b71Sopenharmony_ci
56e41f4b71Sopenharmony_ci其中,includedir表示该数据类型头文件所在目录,includedir中以“.”作为分隔符。namespace表示该数据类型所在命名空间,namespace中同样以“.”作为分隔符。typename表示数据类型,数据类型中不能包含非英文字符类型的其他符号。includedir与namespace之间通过“..”分割,如果类型声明的表达式中不包含“..”,除去最后一个typename之外的字符都会被解析为命名空间。例如:
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci```cpp
59e41f4b71Sopenharmony_cisequenceable a.b..C.D
60e41f4b71Sopenharmony_ci```
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci 上述声明在生成的的C++头文件中将被解析为如下代码:
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci```cpp
65e41f4b71Sopenharmony_ci#include  “a/b/d.h66e41f4b71Sopenharmony_ciusing C::D;
67e41f4b71Sopenharmony_ci```
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ciTS声明放在文件的头部,以 “sequenceable namespace.typename;”的形式声明。具体而言,声明可以有如下形式(idl为对应namespace,MySequenceable为对应typename):
70e41f4b71Sopenharmony_ci
71e41f4b71Sopenharmony_ci```ts
72e41f4b71Sopenharmony_cisequenceable idl.MySequenceable
73e41f4b71Sopenharmony_ci```
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ci其中,namespace是该类型所属的命名空间,typename是类型名。MySequenceable类型表示可以通过Parcel进行跨进程传递。sequenceable数据类型并不在OpenHarmony IDL文件中定义,而是定义在.ts文件中。因此,OpenHarmony IDL工具将根据声明在生成的.ts代码文件中加入如下语句:
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci```ts
78e41f4b71Sopenharmony_ciimport MySequenceable from "./my_sequenceable"
79e41f4b71Sopenharmony_ci```
80e41f4b71Sopenharmony_ci
81e41f4b71Sopenharmony_ci需要注意的是,IDL并不负责该类型的代码实现,仅仅按照指定的形式引入该头文件或import指定模块,并使用该类型,因此开发者需要自行保证引入目录、命名空间及类型的正确性。
82e41f4b71Sopenharmony_ci
83e41f4b71Sopenharmony_ci#### 接口类型
84e41f4b71Sopenharmony_ci 接口类型是指OpenHarmony IDL文件中定义的接口。对于当前IDL文件中定义的接口,可以直接使用它作为方法参数类型或返回值类型。而在其它OpenHarmony IDL文件中定义的接口,则需要在文件的头部进行前置声明。 
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci C++中声明的形式与sequenceable类型相似,具体而言可以有如下形式: 
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci```cpp
89e41f4b71Sopenharmony_ciinterface includedir..namespace.typename
90e41f4b71Sopenharmony_ci```
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci TS中声明的形式,具体而言可以有如下形式: 
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci```ts
95e41f4b71Sopenharmony_ciinterface namespace.interfacename
96e41f4b71Sopenharmony_ci```
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci其中,namespace是该接口所属的命名空间,interfacename是接口名。例如:“interface OHOS.IIdlTestObserver;”声明了在其他OpenHarmony IDL文件定义的IIdlTestObserver接口,该接口可以作为当前定义中方法的参数类型或返回值类型使用。OpenHarmony IDL工具将根据该声明在生成的TS代码文件中加入如下语句:
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci```ts
101e41f4b71Sopenharmony_ciimport IIdlTestObserver from "./i_idl_test_observer"
102e41f4b71Sopenharmony_ci```
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ci#### 数组类型
105e41f4b71Sopenharmony_ci数组类型使用“T[]”表示,其中T可以是基本数据类型、sequenceable数据类型、interface类型和数组类型。该类型在C++生成代码中将被生成为std::vector<T>类型。
106e41f4b71Sopenharmony_ciOpenHarmony IDL数组数据类型与TS数据类型、C++数据类型的对应关系如下表所示:
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci|OpenHarmony IDL数据类型  | C++数据类型           | TS数据类型     |
109e41f4b71Sopenharmony_ci|   -------              |  --------            |  --------    |
110e41f4b71Sopenharmony_ci|T[]                     | std::vector<T> | T[]          |
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci#### 容器类型
113e41f4b71Sopenharmony_ciIDL支持两种容器类型,即List和Map。其中List类型容器的用法为List&lt;T&gt;;Map容器的用法为Map<KT,VT>,其中T、KT、VT为基本数据类型、sequenceable类型、interface类型、数组类型或容器类型。
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ciList类型在C++代码中被映射为std::list,Map容器被映射为std::map。
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ciList类型在TS代码中不支持,Map容器被映射为Map。
118e41f4b71Sopenharmony_ci
119e41f4b71Sopenharmony_ciOpenHarmony IDL容器数据类型与Ts数据类型、C++数据类型的对应关系如下表所示:
120e41f4b71Sopenharmony_ci
121e41f4b71Sopenharmony_ci|OpenHarmony IDL数据类型  | C++数据类型       | TS数据类型     |
122e41f4b71Sopenharmony_ci|   --------             |  --------        |  -------     |
123e41f4b71Sopenharmony_ci|List&lt;T&gt;           | std::list        | 不支持        |
124e41f4b71Sopenharmony_ci|Map<KT,VT>              | std::map         | Map          |
125e41f4b71Sopenharmony_ci
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci### IDL文件编写规范
128e41f4b71Sopenharmony_ci一个idl文件只能定义一个interface类型,且该interface名称必须和文件名相同。idl文件的接口定义使用BNF范式描述,其基本定义的形式如下:
129e41f4b71Sopenharmony_ci
130e41f4b71Sopenharmony_ci```
131e41f4b71Sopenharmony_ci[<*interface_attr_declaration*>]interface<*interface_name_with_namespace*>{<*method_declaration*>}
132e41f4b71Sopenharmony_ci```
133e41f4b71Sopenharmony_ci
134e41f4b71Sopenharmony_ci其中,<*interface_attr_declaration*>表示接口属性声明。当前仅支持“oneway”属性,表示该接口中的接口都是单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。接口名需要包含完整的接口头文件目录及命名空间,且必须包含方法声明,不允许出现空接口。
135e41f4b71Sopenharmony_ci接口内的方法声明形式为:
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci```
138e41f4b71Sopenharmony_ci[<*method_attr_declaration*>]<*result_type*><*method_declaration*>
139e41f4b71Sopenharmony_ci```
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ci其中,<*method_attr_declaration*>表示接口属性说明。当前仅支持“oneway”属性,表示该方法为单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。<*result_type*>为返回值类型,<*method_declaration*>是方法名和各个参数声明。
142e41f4b71Sopenharmony_ci参数声明的形式为:
143e41f4b71Sopenharmony_ci
144e41f4b71Sopenharmony_ci```
145e41f4b71Sopenharmony_ci[<*formal_param_attr*>]<*type*><*identifier*>
146e41f4b71Sopenharmony_ci```
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ci其中<*formal_param_attr*>的值为“in”,“out”,“inout”,分别表示该参数是输入参数,输出参数或输入输出参数。需要注意的是,如果一个方法被声明为oneway,则该方法不允许有输出类型的参数(及输入输出类型)和返回值。
149e41f4b71Sopenharmony_ci
150e41f4b71Sopenharmony_ci## 开发步骤
151e41f4b71Sopenharmony_ci
152e41f4b71Sopenharmony_ci### 获取IDL工具
153e41f4b71Sopenharmony_ci#### 方法一(推荐):
154e41f4b71Sopenharmony_ci1. 在linux系统,下载OpenHarmony的两个仓:ability_idl_tool代码仓、third_party_bounds_checking_function代码仓。
155e41f4b71Sopenharmony_ci2. 进入ability_idl_tool代码仓,在Makefile所在目录执行make命令(**注意修改MakefileLinux中关于bounds_checking_function的相对位置**)。
156e41f4b71Sopenharmony_ci3. make执行完成后,在当前目录下会生成idl-gen可执行文件,可用于idl文件本地调试。
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci#### 方法二:
159e41f4b71Sopenharmony_ci首先,打开DevEco Studio—>Tools—>SDK Manager,查看OpenHarmony SDK的本地安装路径,此处以DevEco Studio 3.0.0.993版本为例,查看方式如下图所示。
160e41f4b71Sopenharmony_ci![SDKpath](./figures/SDKpath.png)
161e41f4b71Sopenharmony_ci![SDKpath](./figures/SDKpath2.png)
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci进入对应路径后,查看toolchains->3.x.x.x(对应版本号命名文件夹)下是否存在idl工具的可执行文件。
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci> **注意**:
166e41f4b71Sopenharmony_ci> 
167e41f4b71Sopenharmony_ci> 请保证使用最新版的SDK,版本老旧可能导致部分语句报错。
168e41f4b71Sopenharmony_ci
169e41f4b71Sopenharmony_ci若不存在,可对应版本前往[docs仓版本目录](../../release-notes)下载SDK包,以[3.2Beta3版本](../../release-notes/OpenHarmony-v3.2-beta3.md)为例,可通过镜像站点获取。
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci关于如何替换DevEco Studio的SDK包具体操作,参考[full-SDK替换指南](../faqs/full-sdk-compile-guide.md)中的替换方法。
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci得到idl工具的可执行文件后,根据具体场景进行后续开发步骤。
174e41f4b71Sopenharmony_ci
175e41f4b71Sopenharmony_ci### TS开发步骤
176e41f4b71Sopenharmony_ci
177e41f4b71Sopenharmony_ci#### 创建.idl文件
178e41f4b71Sopenharmony_ci
179e41f4b71Sopenharmony_ci 开发者可以使用TS编程语言构建.idl文件。
180e41f4b71Sopenharmony_ci
181e41f4b71Sopenharmony_ci 例如,此处构建一个名为IIdlTestService.idl的文件,文件内具体内容如下:  
182e41f4b71Sopenharmony_ci
183e41f4b71Sopenharmony_ci```cpp
184e41f4b71Sopenharmony_ci  interface OHOS.IIdlTestService {
185e41f4b71Sopenharmony_ci      int TestIntTransaction([in] int data);
186e41f4b71Sopenharmony_ci      void TestStringTransaction([in] String data);
187e41f4b71Sopenharmony_ci      void TestMapTransaction([in] Map<int, int> data);
188e41f4b71Sopenharmony_ci      int TestArrayTransaction([in] String[] data);
189e41f4b71Sopenharmony_ci  }
190e41f4b71Sopenharmony_ci```
191e41f4b71Sopenharmony_ci
192e41f4b71Sopenharmony_ci在idl的可执行文件所在文件夹下执行命令 `idl -gen-ts -d dir -c dir/IIdlTestService.idl`。
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci-d后的dir为目标输出目录,以输出文件夹名为IIdlTestServiceTs为例,在idl可执行文件所在目录下执行`idl -gen-ts -d IIdlTestServiceTs -c IIdlTestServiceTs/IIdlTestService.idl`,将会在执行环境的dir目录(即IIdlTestServiceTs目录)中生成接口文件、Stub文件、Proxy文件。
195e41f4b71Sopenharmony_ci
196e41f4b71Sopenharmony_ci> **注意**:生成的接口类文件名称和.idl文件名称保持一致,否则会生成代码时会出现错误。
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci以名为`IIdlTestService.idl`的.idl文件、目标输出文件夹为IIdlTestServiceTs为例,其目录结构应类似于:
199e41f4b71Sopenharmony_ci
200e41f4b71Sopenharmony_ci```
201e41f4b71Sopenharmony_ci├── IIdlTestServiceTs  # idl代码输出文件夹
202e41f4b71Sopenharmony_ci│   ├── i_idl_test_service.ts  # 生成文件
203e41f4b71Sopenharmony_ci│   ├── idl_test_service_proxy.ts  # 生成文件
204e41f4b71Sopenharmony_ci│   ├── idl_test_service_stub.ts  # 生成文件
205e41f4b71Sopenharmony_ci│   └── IIdlTestService.idl  # 构造的.idl文件
206e41f4b71Sopenharmony_ci└── idl.exe  # idl的可执行文件
207e41f4b71Sopenharmony_ci```
208e41f4b71Sopenharmony_ci
209e41f4b71Sopenharmony_ci#### 服务端公开接口
210e41f4b71Sopenharmony_ci
211e41f4b71Sopenharmony_ciOpenHarmony IDL工具生成的Stub类是接口类的抽象实现,并且会声明.idl文件中的所有方法。 
212e41f4b71Sopenharmony_ci
213e41f4b71Sopenharmony_ci```ts
214e41f4b71Sopenharmony_ciimport {testIntTransactionCallback} from "./i_idl_test_service";
215e41f4b71Sopenharmony_ciimport {testStringTransactionCallback} from "./i_idl_test_service";
216e41f4b71Sopenharmony_ciimport {testMapTransactionCallback} from "./i_idl_test_service";
217e41f4b71Sopenharmony_ciimport {testArrayTransactionCallback} from "./i_idl_test_service";
218e41f4b71Sopenharmony_ciimport IIdlTestService from "./i_idl_test_service";
219e41f4b71Sopenharmony_ciimport rpc from "@ohos.rpc";
220e41f4b71Sopenharmony_ci
221e41f4b71Sopenharmony_ciexport default class IdlTestServiceStub extends rpc.RemoteObject implements IIdlTestService {
222e41f4b71Sopenharmony_ci    constructor(des: string) {
223e41f4b71Sopenharmony_ci        super(des);
224e41f4b71Sopenharmony_ci    }
225e41f4b71Sopenharmony_ci    
226e41f4b71Sopenharmony_ci    async onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence,
227e41f4b71Sopenharmony_ci        option: rpc.MessageOption): Promise<boolean> {
228e41f4b71Sopenharmony_ci        console.log("onRemoteMessageRequest called, code = " + code);
229e41f4b71Sopenharmony_ci        if (code == IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION) {
230e41f4b71Sopenharmony_ci            let _data = data.readInt();
231e41f4b71Sopenharmony_ci            this.testIntTransaction(_data, (errCode: number, returnValue: number) => {
232e41f4b71Sopenharmony_ci                reply.writeInt(errCode);
233e41f4b71Sopenharmony_ci                if (errCode == 0) {
234e41f4b71Sopenharmony_ci                    reply.writeInt(returnValue);
235e41f4b71Sopenharmony_ci                }
236e41f4b71Sopenharmony_ci            });
237e41f4b71Sopenharmony_ci            return true;
238e41f4b71Sopenharmony_ci        } else if (code == IdlTestServiceStub.COMMAND_TEST_STRING_TRANSACTION) {
239e41f4b71Sopenharmony_ci            let _data = data.readString();
240e41f4b71Sopenharmony_ci            this.testStringTransaction(_data, (errCode: number) => {
241e41f4b71Sopenharmony_ci                reply.writeInt(errCode);
242e41f4b71Sopenharmony_ci            });
243e41f4b71Sopenharmony_ci            return true;
244e41f4b71Sopenharmony_ci        } else if (code == IdlTestServiceStub.COMMAND_TEST_MAP_TRANSACTION) {
245e41f4b71Sopenharmony_ci            let _data: Map<number, number> = new Map();
246e41f4b71Sopenharmony_ci            let _dataSize = data.readInt();
247e41f4b71Sopenharmony_ci            for (let i = 0; i < _dataSize; ++i) {
248e41f4b71Sopenharmony_ci                let key = data.readInt();
249e41f4b71Sopenharmony_ci                let value = data.readInt();
250e41f4b71Sopenharmony_ci                _data.set(key, value);
251e41f4b71Sopenharmony_ci            }
252e41f4b71Sopenharmony_ci            this.testMapTransaction(_data, (errCode: number) => {
253e41f4b71Sopenharmony_ci                reply.writeInt(errCode);
254e41f4b71Sopenharmony_ci            });
255e41f4b71Sopenharmony_ci            return true;
256e41f4b71Sopenharmony_ci        } else if (code == IdlTestServiceStub.COMMAND_TEST_ARRAY_TRANSACTION) {
257e41f4b71Sopenharmony_ci            let _data = data.readStringArray();
258e41f4b71Sopenharmony_ci            this.testArrayTransaction(_data, (errCode: number, returnValue: number) => {
259e41f4b71Sopenharmony_ci                reply.writeInt(errCode);
260e41f4b71Sopenharmony_ci                if (errCode == 0) {
261e41f4b71Sopenharmony_ci                    reply.writeInt(returnValue);
262e41f4b71Sopenharmony_ci                }
263e41f4b71Sopenharmony_ci            });
264e41f4b71Sopenharmony_ci            return true;
265e41f4b71Sopenharmony_ci        } else {
266e41f4b71Sopenharmony_ci            console.log("invalid request code" + code);
267e41f4b71Sopenharmony_ci        }
268e41f4b71Sopenharmony_ci        return false;
269e41f4b71Sopenharmony_ci    }
270e41f4b71Sopenharmony_ci    
271e41f4b71Sopenharmony_ci    testIntTransaction(data: number, callback: testIntTransactionCallback): void{}
272e41f4b71Sopenharmony_ci    testStringTransaction(data: string, callback: testStringTransactionCallback): void{}
273e41f4b71Sopenharmony_ci    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void{}
274e41f4b71Sopenharmony_ci    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void{}
275e41f4b71Sopenharmony_ci
276e41f4b71Sopenharmony_ci    static readonly COMMAND_TEST_INT_TRANSACTION = 1;
277e41f4b71Sopenharmony_ci    static readonly COMMAND_TEST_STRING_TRANSACTION = 2;
278e41f4b71Sopenharmony_ci    static readonly COMMAND_TEST_MAP_TRANSACTION = 3;
279e41f4b71Sopenharmony_ci    static readonly COMMAND_TEST_ARRAY_TRANSACTION = 4;
280e41f4b71Sopenharmony_ci}
281e41f4b71Sopenharmony_ci```
282e41f4b71Sopenharmony_ci
283e41f4b71Sopenharmony_ci开发者需要继承.idl文件中定义的接口类并实现其中的方法。在本示例中,我们继承了IdlTestServiceStub接口类并实现了其中的testIntTransaction、testStringTransaction、testMapTransaction和testArrayTransaction方法。具体的示例代码如下:
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ci```ts
286e41f4b71Sopenharmony_ciimport {testIntTransactionCallback} from "./i_idl_test_service"
287e41f4b71Sopenharmony_ciimport {testStringTransactionCallback} from "./i_idl_test_service"
288e41f4b71Sopenharmony_ciimport {testMapTransactionCallback} from "./i_idl_test_service";
289e41f4b71Sopenharmony_ciimport {testArrayTransactionCallback} from "./i_idl_test_service";
290e41f4b71Sopenharmony_ciimport IdlTestServiceStub from "./idl_test_service_stub"
291e41f4b71Sopenharmony_ci
292e41f4b71Sopenharmony_ci
293e41f4b71Sopenharmony_ciclass IdlTestImp extends IdlTestServiceStub {
294e41f4b71Sopenharmony_ci
295e41f4b71Sopenharmony_ci    testIntTransaction(data: number, callback: testIntTransactionCallback): void
296e41f4b71Sopenharmony_ci    {
297e41f4b71Sopenharmony_ci        callback(0, data + 1);
298e41f4b71Sopenharmony_ci    }
299e41f4b71Sopenharmony_ci    testStringTransaction(data: string, callback: testStringTransactionCallback): void
300e41f4b71Sopenharmony_ci    {
301e41f4b71Sopenharmony_ci        callback(0);
302e41f4b71Sopenharmony_ci    }
303e41f4b71Sopenharmony_ci    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void
304e41f4b71Sopenharmony_ci    {
305e41f4b71Sopenharmony_ci        callback(0);
306e41f4b71Sopenharmony_ci    }
307e41f4b71Sopenharmony_ci    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void
308e41f4b71Sopenharmony_ci    {
309e41f4b71Sopenharmony_ci        callback(0, 1);
310e41f4b71Sopenharmony_ci    }
311e41f4b71Sopenharmony_ci}
312e41f4b71Sopenharmony_ci```
313e41f4b71Sopenharmony_ci
314e41f4b71Sopenharmony_ci在服务实现接口后,需要向客户端公开该接口,以便客户端进程绑定。如果开发者的服务要公开该接口,请扩展Ability并实现onConnect()从而返回IRemoteObject,以便客户端能与服务进程交互。服务端向客户端公开IRemoteAbility接口的代码示例如下:
315e41f4b71Sopenharmony_ci
316e41f4b71Sopenharmony_ci```ts
317e41f4b71Sopenharmony_ciimport Want from '@ohos.app.ability.Want';
318e41f4b71Sopenharmony_ciimport rpc from "@ohos.rpc";
319e41f4b71Sopenharmony_ci
320e41f4b71Sopenharmony_ciclass ServiceAbility {
321e41f4b71Sopenharmony_ci  onStart() {
322e41f4b71Sopenharmony_ci    console.info('ServiceAbility onStart');
323e41f4b71Sopenharmony_ci  }
324e41f4b71Sopenharmony_ci  onStop() {
325e41f4b71Sopenharmony_ci    console.info('ServiceAbility onStop');
326e41f4b71Sopenharmony_ci  }
327e41f4b71Sopenharmony_ci  onCommand(want: Want, startId: number) {
328e41f4b71Sopenharmony_ci    console.info('ServiceAbility onCommand');
329e41f4b71Sopenharmony_ci  }
330e41f4b71Sopenharmony_ci  onConnect(want: Want) {
331e41f4b71Sopenharmony_ci    console.info('ServiceAbility onConnect');
332e41f4b71Sopenharmony_ci    try {
333e41f4b71Sopenharmony_ci      console.log('ServiceAbility want:' + typeof(want));
334e41f4b71Sopenharmony_ci      console.log('ServiceAbility want:' + JSON.stringify(want));
335e41f4b71Sopenharmony_ci      console.log('ServiceAbility want name:' + want.bundleName)
336e41f4b71Sopenharmony_ci    } catch(err) {
337e41f4b71Sopenharmony_ci      console.log('ServiceAbility error:' + err)
338e41f4b71Sopenharmony_ci    }
339e41f4b71Sopenharmony_ci    console.info('ServiceAbility onConnect end');
340e41f4b71Sopenharmony_ci    return new IdlTestImp('connect') as rpc.RemoteObject;
341e41f4b71Sopenharmony_ci  }
342e41f4b71Sopenharmony_ci  onDisconnect(want: Want) {
343e41f4b71Sopenharmony_ci    console.info('ServiceAbility onDisconnect');
344e41f4b71Sopenharmony_ci    console.info('ServiceAbility want:' + JSON.stringify(want));
345e41f4b71Sopenharmony_ci  }
346e41f4b71Sopenharmony_ci}
347e41f4b71Sopenharmony_ci
348e41f4b71Sopenharmony_ciexport default new ServiceAbility()
349e41f4b71Sopenharmony_ci```
350e41f4b71Sopenharmony_ci
351e41f4b71Sopenharmony_ci#### 客户端调用IPC方法
352e41f4b71Sopenharmony_ci
353e41f4b71Sopenharmony_ci客户端调用connectServiceExtensionAbility()以连接服务时,客户端的onAbilityConnectDone中的onConnect回调会接收服务的onConnect()方法返回的IRemoteObject实例。由于客户端和服务在不同应用内,所以客户端应用的目录内必须包含.idl文件(SDK工具会自动生成Proxy代理类)的副本。客户端的onAbilityConnectDone中的onConnect回调会接收服务的onConnect()方法返回的IRemoteObject实例,使用IRemoteObject创建IdlTestServiceProxy类的实例对象testProxy,然后调用相关IPC方法。示例代码如下:
354e41f4b71Sopenharmony_ci
355e41f4b71Sopenharmony_ci```ts
356e41f4b71Sopenharmony_ciimport common from '@ohos.app.ability.common';
357e41f4b71Sopenharmony_ciimport Want from '@ohos.app.ability.Want';
358e41f4b71Sopenharmony_ciimport IdlTestServiceProxy from './idl_test_service_proxy'
359e41f4b71Sopenharmony_ci
360e41f4b71Sopenharmony_cifunction callbackTestIntTransaction(result: number, ret: number): void {
361e41f4b71Sopenharmony_ci  if (result == 0 && ret == 124) {
362e41f4b71Sopenharmony_ci    console.log('case 1 success');
363e41f4b71Sopenharmony_ci  }
364e41f4b71Sopenharmony_ci}
365e41f4b71Sopenharmony_ci
366e41f4b71Sopenharmony_cifunction callbackTestStringTransaction(result: number): void {
367e41f4b71Sopenharmony_ci  if (result == 0) {
368e41f4b71Sopenharmony_ci    console.log('case 2 success');
369e41f4b71Sopenharmony_ci  }
370e41f4b71Sopenharmony_ci}
371e41f4b71Sopenharmony_ci
372e41f4b71Sopenharmony_cifunction callbackTestMapTransaction(result: number): void {
373e41f4b71Sopenharmony_ci  if (result == 0) {
374e41f4b71Sopenharmony_ci    console.log('case 3 success');
375e41f4b71Sopenharmony_ci  }
376e41f4b71Sopenharmony_ci}
377e41f4b71Sopenharmony_ci
378e41f4b71Sopenharmony_cifunction callbackTestArrayTransaction(result: number, ret: number): void {
379e41f4b71Sopenharmony_ci  if (result == 0 && ret == 124) {
380e41f4b71Sopenharmony_ci    console.log('case 4 success');
381e41f4b71Sopenharmony_ci  }
382e41f4b71Sopenharmony_ci}
383e41f4b71Sopenharmony_ci
384e41f4b71Sopenharmony_cilet onAbilityConnectDone: common.ConnectOptions = {
385e41f4b71Sopenharmony_ci  onConnect: (elementName, proxy) => {
386e41f4b71Sopenharmony_ci    let testProxy: IdlTestServiceProxy = new IdlTestServiceProxy(proxy);
387e41f4b71Sopenharmony_ci    let testMap: Map<number, number> = new Map();
388e41f4b71Sopenharmony_ci    testMap.set(1, 1);
389e41f4b71Sopenharmony_ci    testMap.set(1, 2);
390e41f4b71Sopenharmony_ci    testProxy.testIntTransaction(123, callbackTestIntTransaction);
391e41f4b71Sopenharmony_ci    testProxy.testStringTransaction('hello', callbackTestStringTransaction);
392e41f4b71Sopenharmony_ci    testProxy.testMapTransaction(testMap, callbackTestMapTransaction);
393e41f4b71Sopenharmony_ci    testProxy.testArrayTransaction(['1','2'], callbackTestMapTransaction);
394e41f4b71Sopenharmony_ci  },
395e41f4b71Sopenharmony_ci  onDisconnect: (elementName) => {
396e41f4b71Sopenharmony_ci    console.log('onDisconnectService onDisconnect');
397e41f4b71Sopenharmony_ci  },
398e41f4b71Sopenharmony_ci  onFailed: (code) => {
399e41f4b71Sopenharmony_ci    console.log('onDisconnectService onFailed');
400e41f4b71Sopenharmony_ci  }
401e41f4b71Sopenharmony_ci};
402e41f4b71Sopenharmony_ci
403e41f4b71Sopenharmony_cilet context: common.UIAbilityContext = this.context;
404e41f4b71Sopenharmony_ci
405e41f4b71Sopenharmony_cifunction connectAbility(): void {
406e41f4b71Sopenharmony_ci    let want: Want = {
407e41f4b71Sopenharmony_ci        bundleName: 'com.example.myapplicationidl',
408e41f4b71Sopenharmony_ci        abilityName: 'com.example.myapplicationidl.ServiceAbility'
409e41f4b71Sopenharmony_ci    };
410e41f4b71Sopenharmony_ci    let connectionId = -1;
411e41f4b71Sopenharmony_ci    connectionId = context.connectServiceExtensionAbility(want, onAbilityConnectDone);
412e41f4b71Sopenharmony_ci}
413e41f4b71Sopenharmony_ci
414e41f4b71Sopenharmony_ci
415e41f4b71Sopenharmony_ci```
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ci#### IPC传递sequenceable对象
418e41f4b71Sopenharmony_ci
419e41f4b71Sopenharmony_ci开发者可以通过 IPC 接口,将某个类从一个进程发送至另一个进程。但是,必须确保 IPC 通道的另一端可使用该类的代码,并且该类必须支持marshalling和unmarshalling方法。系统需要通过marshalling和unmarshalling方法将对象序列化和反序列化成各进程能识别的对象。
420e41f4b71Sopenharmony_ci
421e41f4b71Sopenharmony_ci **如需创建支持sequenceable 类型数据,开发者必须执行以下操作:** 
422e41f4b71Sopenharmony_ci
423e41f4b71Sopenharmony_ci1. 实现marshalling方法,它会获取对象的当前状态并将其序列化后写入Parcel。
424e41f4b71Sopenharmony_ci2. 实现unmarshalling方法,它会从Parcel中反序列化出对象。
425e41f4b71Sopenharmony_ci
426e41f4b71Sopenharmony_ciMySequenceable类的代码示例如下:
427e41f4b71Sopenharmony_ci
428e41f4b71Sopenharmony_ci```ts
429e41f4b71Sopenharmony_ciimport rpc from '@ohos.rpc';
430e41f4b71Sopenharmony_ciexport default class MySequenceable implements rpc.Sequenceable {
431e41f4b71Sopenharmony_ci    constructor(num: number, str: string) {
432e41f4b71Sopenharmony_ci        this.num = num;
433e41f4b71Sopenharmony_ci        this.str = str;
434e41f4b71Sopenharmony_ci    }
435e41f4b71Sopenharmony_ci    getNum() : number {
436e41f4b71Sopenharmony_ci        return this.num;
437e41f4b71Sopenharmony_ci    }
438e41f4b71Sopenharmony_ci    getString() : string {
439e41f4b71Sopenharmony_ci        return this.str;
440e41f4b71Sopenharmony_ci    }
441e41f4b71Sopenharmony_ci    marshalling(messageParcel: rpc.MessageParcel) {
442e41f4b71Sopenharmony_ci        messageParcel.writeInt(this.num);
443e41f4b71Sopenharmony_ci        messageParcel.writeString(this.str);
444e41f4b71Sopenharmony_ci        return true;
445e41f4b71Sopenharmony_ci    }
446e41f4b71Sopenharmony_ci    unmarshalling(messageParcel: rpc.MessageParcel) {
447e41f4b71Sopenharmony_ci        this.num = messageParcel.readInt();
448e41f4b71Sopenharmony_ci        this.str = messageParcel.readString();
449e41f4b71Sopenharmony_ci        return true;
450e41f4b71Sopenharmony_ci    }
451e41f4b71Sopenharmony_ci    private num: number;
452e41f4b71Sopenharmony_ci    private str: string;
453e41f4b71Sopenharmony_ci}
454e41f4b71Sopenharmony_ci```
455e41f4b71Sopenharmony_ci
456e41f4b71Sopenharmony_ci### C++开发SA步骤(编译期自动生成SA接口模板代码)
457e41f4b71Sopenharmony_ci
458e41f4b71Sopenharmony_ci#### 创建.idl文件
459e41f4b71Sopenharmony_ci
460e41f4b71Sopenharmony_ci开发者使用C++编程语言构建.idl文件。
461e41f4b71Sopenharmony_ci
462e41f4b71Sopenharmony_ci例如,此处构建一个名为IQuickFixManager.idl的文件,文件内具体内容如下:
463e41f4b71Sopenharmony_ci
464e41f4b71Sopenharmony_ci```
465e41f4b71Sopenharmony_ci/*
466e41f4b71Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
467e41f4b71Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
468e41f4b71Sopenharmony_ci * you may not use this file except in compliance with the License.
469e41f4b71Sopenharmony_ci * You may obtain a copy of the License at
470e41f4b71Sopenharmony_ci *
471e41f4b71Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
472e41f4b71Sopenharmony_ci *
473e41f4b71Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
474e41f4b71Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
475e41f4b71Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
476e41f4b71Sopenharmony_ci * See the License for the specific language governing permissions and
477e41f4b71Sopenharmony_ci * limitations under the License.
478e41f4b71Sopenharmony_ci */
479e41f4b71Sopenharmony_ci
480e41f4b71Sopenharmony_cisequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo;
481e41f4b71Sopenharmony_ciinterface OHOS.AAFwk.IQuickFixManager {
482e41f4b71Sopenharmony_ci    void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
483e41f4b71Sopenharmony_ci    void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
484e41f4b71Sopenharmony_ci    void RevokeQuickFix([in] String bundleName);
485e41f4b71Sopenharmony_ci}
486e41f4b71Sopenharmony_ci```
487e41f4b71Sopenharmony_ci
488e41f4b71Sopenharmony_ci#### 修改BUILD.gn文件
489e41f4b71Sopenharmony_ci提供两种配置方法,选择其中一种即可
490e41f4b71Sopenharmony_ci
491e41f4b71Sopenharmony_ci##### 修改方法一(推荐,支持批量处理idl文件并编译为so)
492e41f4b71Sopenharmony_ci
493e41f4b71Sopenharmony_ci1. 导入IDL工具模板到当前BUILD.gn文件。
494e41f4b71Sopenharmony_ci
495e41f4b71Sopenharmony_ci   ```bash
496e41f4b71Sopenharmony_ci   # 此处不需要修改,直接复制到gn中即可
497e41f4b71Sopenharmony_ci   import("//foundation/ability/idl_tool/idl_config.gni")
498e41f4b71Sopenharmony_ci   ```
499e41f4b71Sopenharmony_ci
500e41f4b71Sopenharmony_ci2. 调用IDL工具生成C++模板文件。
501e41f4b71Sopenharmony_ci
502e41f4b71Sopenharmony_ci   ```bash
503e41f4b71Sopenharmony_ci   
504e41f4b71Sopenharmony_ci   # 使用idl_gen_interface生成模板文件、输入的参数名在deps中会使用
505e41f4b71Sopenharmony_ci   idl_gen_interface("EEEFFFGGG") {
506e41f4b71Sopenharmony_ci     # 开发者定义的.idl名,须与gn文件在同一路径下
507e41f4b71Sopenharmony_ci     sources = [
508e41f4b71Sopenharmony_ci      "IAxxBxxCxx.idl",
509e41f4b71Sopenharmony_ci      "IAxxBxxCxx2.idl",
510e41f4b71Sopenharmony_ci     ]
511e41f4b71Sopenharmony_ci
512e41f4b71Sopenharmony_ci     # 根据idl文件中对自定义对象的使用,编译为so时需要增加自定义对应使用的cpp的编译,默认为空
513e41f4b71Sopenharmony_ci     sources_cpp = []
514e41f4b71Sopenharmony_ci
515e41f4b71Sopenharmony_ci     # 编译so时增加configs配置
516e41f4b71Sopenharmony_ci     configs = []
517e41f4b71Sopenharmony_ci
518e41f4b71Sopenharmony_ci     # 编译so时增加public_deps配置
519e41f4b71Sopenharmony_ci     sequenceable_pub_deps = []
520e41f4b71Sopenharmony_ci
521e41f4b71Sopenharmony_ci     # 编译so时增加external_deps配置
522e41f4b71Sopenharmony_ci     sequeceable_ext_deps = []
523e41f4b71Sopenharmony_ci
524e41f4b71Sopenharmony_ci     # 编译so时增加innerapi_tags
525e41f4b71Sopenharmony_ci     innerapi_tags = ""
526e41f4b71Sopenharmony_ci
527e41f4b71Sopenharmony_ci     # 编译so时增加sanitize
528e41f4b71Sopenharmony_ci     sanitize = ""
529e41f4b71Sopenharmony_ci
530e41f4b71Sopenharmony_ci
531e41f4b71Sopenharmony_ci     # 开启hitrace,值是hitrace_meter.h文件中定义的uint64_t类型标识,需要填入常量的变量名
532e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
533e41f4b71Sopenharmony_ci     
534e41f4b71Sopenharmony_ci     # 开启hilog,Domain ID 使用16进制的整数
535e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
536e41f4b71Sopenharmony_ci     # 开启hilog,字符串类型tag名、一般为子系统名称
537e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"
538e41f4b71Sopenharmony_ci
539e41f4b71Sopenharmony_ci     # 必填:编译so时增加subsystem_name,与业务保持一致,如quick_fix使用:
540e41f4b71Sopenharmony_ci     subsystem_name = "ability"
541e41f4b71Sopenharmony_ci     # 必填:编译so时增加part_name,与业务保持一致,如quick_fix使用:
542e41f4b71Sopenharmony_ci     part_name = "ability_runtime"
543e41f4b71Sopenharmony_ci   }
544e41f4b71Sopenharmony_ci   ```
545e41f4b71Sopenharmony_ci
546e41f4b71Sopenharmony_ci   配置hilog,参数log_domainid和log_tag必须成对出现,若只写一个会编译错误,quick_fix示例如下:
547e41f4b71Sopenharmony_ci
548e41f4b71Sopenharmony_ci   ```bash
549e41f4b71Sopenharmony_ci   idl_gen_interface("quickfix_manager_interface") {
550e41f4b71Sopenharmony_ci     sources = [
551e41f4b71Sopenharmony_ci      "IQuickFixManager.idl"
552e41f4b71Sopenharmony_ci     ]
553e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
554e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
555e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"    #只有一个log_tag,编译会错误,同理只有log_domainid,编译也会错误
556e41f4b71Sopenharmony_ci   }
557e41f4b71Sopenharmony_ci   ```
558e41f4b71Sopenharmony_ci
559e41f4b71Sopenharmony_ci3. 在BUILD.gn中添加依赖“EEEFFFGGG”。
560e41f4b71Sopenharmony_ci
561e41f4b71Sopenharmony_ci   ```bash
562e41f4b71Sopenharmony_ci   deps = [
563e41f4b71Sopenharmony_ci      # 使用idl_gen_interface函数参数名,前面加上lib,后面加上_proxy和_stub即为生成的so名称
564e41f4b71Sopenharmony_ci      ":libEEEFFFGGG_proxy", # 如果需要 proxy 的so,加上这个依赖
565e41f4b71Sopenharmony_ci      ":libEEEFFFGGG_stub", # 如果需要 stub 的so,加上这个依赖
566e41f4b71Sopenharmony_ci     ]
567e41f4b71Sopenharmony_ci   ```
568e41f4b71Sopenharmony_ci
569e41f4b71Sopenharmony_ci   deps添加的依赖名,必须同idl_gen_interface函数参数名相同,quick_fix示例如下:
570e41f4b71Sopenharmony_ci
571e41f4b71Sopenharmony_ci   ```bash
572e41f4b71Sopenharmony_ci   idl_gen_interface("quickfix_manager_interface") {
573e41f4b71Sopenharmony_ci     sources = [
574e41f4b71Sopenharmony_ci      "IQuickFixManager.idl"
575e41f4b71Sopenharmony_ci     ]
576e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
577e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
578e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"
579e41f4b71Sopenharmony_ci   }
580e41f4b71Sopenharmony_ci   deps = [
581e41f4b71Sopenharmony_ci    "${ability_runtime_innerkits_path}/app_manager:app_manager",
582e41f4b71Sopenharmony_ci    ":libquickfix_manager_interface_proxy", # idl_gen_interface函数参数名前面加上lib,后面加上_proxy
583e41f4b71Sopenharmony_ci    ":libquickfix_manager_interface_stub", # idl_gen_interface函数参数名前面加上lib,后面加上_stub
584e41f4b71Sopenharmony_ci   ]
585e41f4b71Sopenharmony_ci   ```
586e41f4b71Sopenharmony_ci
587e41f4b71Sopenharmony_ci6. 在BUILD.gn中添加模板文件的外部依赖。
588e41f4b71Sopenharmony_ci
589e41f4b71Sopenharmony_ci   模板文件的外部依赖需要自己添加到external_deps里。
590e41f4b71Sopenharmony_ci   若之前已存在,不需要重复添加,若重复添加会导致编译错误。
591e41f4b71Sopenharmony_ci
592e41f4b71Sopenharmony_ci   ```bash
593e41f4b71Sopenharmony_ci     external_deps = [
594e41f4b71Sopenharmony_ci     # 模板文件必须的依赖
595e41f4b71Sopenharmony_ci     "c_utils:utils",
596e41f4b71Sopenharmony_ci     # hilog输出必须的依赖
597e41f4b71Sopenharmony_ci     "hilog:libhilog",
598e41f4b71Sopenharmony_ci     # hitrace输出必须的依赖(如果idl_gen_interface中未配置hitrace,则不需要此依赖)
599e41f4b71Sopenharmony_ci     "hitrace:hitrace_meter",
600e41f4b71Sopenharmony_ci     # 模板文件必须的依赖
601e41f4b71Sopenharmony_ci     "ipc:ipc_core",
602e41f4b71Sopenharmony_ci   ]
603e41f4b71Sopenharmony_ci   ```
604e41f4b71Sopenharmony_ci
605e41f4b71Sopenharmony_ci##### 修改方法二
606e41f4b71Sopenharmony_ci
607e41f4b71Sopenharmony_ci1. 导入IDL工具模板到当前BUILD.gn文件。
608e41f4b71Sopenharmony_ci
609e41f4b71Sopenharmony_ci   ```bash
610e41f4b71Sopenharmony_ci   # 此处不需要修改,直接复制到gn中即可
611e41f4b71Sopenharmony_ci   import("//foundation/ability/idl_tool/idl_config.gni")
612e41f4b71Sopenharmony_ci   ```
613e41f4b71Sopenharmony_ci
614e41f4b71Sopenharmony_ci2. 调用IDL工具生成C++模板文件。
615e41f4b71Sopenharmony_ci
616e41f4b71Sopenharmony_ci   示例中的axx_bxx_cxx需要替换为生成的stub和proxy的.cpp名。
617e41f4b71Sopenharmony_ci
618e41f4b71Sopenharmony_ci   ```bash
619e41f4b71Sopenharmony_ci   idl_interface_sources = [
620e41f4b71Sopenharmony_ci     # axx_bxx_cxx为需要修改为生成proxy的.cpp名
621e41f4b71Sopenharmony_ci     "${target_gen_dir}/axx_bxx_cxx_proxy.cpp",                                            
622e41f4b71Sopenharmony_ci     # axx_bxx_cxx为需要修改为生成stub的.cpp名
623e41f4b71Sopenharmony_ci     "${target_gen_dir}/axx_bxx_cxx_stub.cpp",
624e41f4b71Sopenharmony_ci   ]
625e41f4b71Sopenharmony_ci   
626e41f4b71Sopenharmony_ci   # 使用idl_gen_interface生成模板文件、需输入参数名后面的deps中会使用
627e41f4b71Sopenharmony_ci   idl_gen_interface("EEEFFFGGG") {
628e41f4b71Sopenharmony_ci     # 开发者定义的.idl名,与gn文件在同一路径下
629e41f4b71Sopenharmony_ci     src_idl = rebase_path("IAxxBxxCxx.idl")
630e41f4b71Sopenharmony_ci     # proxy和stub模板.cpp文件, 此处不需要修改,直接复制到gn中即可
631e41f4b71Sopenharmony_ci     dst_file = string_join(",", idl_interface_sources)
632e41f4b71Sopenharmony_ci     # 开启hitrace,值是hitrace_meter.h文件中定义的uint64_t类型标识,需要填入常量的变量名
633e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
634e41f4b71Sopenharmony_ci     # 开启hilog,Domain ID 使用16进制的整数
635e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
636e41f4b71Sopenharmony_ci     # 开启hilog,字符串类型tag名、一般为子系统名称
637e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"
638e41f4b71Sopenharmony_ci   }
639e41f4b71Sopenharmony_ci   ```
640e41f4b71Sopenharmony_ci
641e41f4b71Sopenharmony_ci   axx_bxx_cxx_proxy.cppaxx_bxx_cxx_stub.cpp的命名与.idl文件小写名相同,遇到大写时加"_"。
642e41f4b71Sopenharmony_ci
643e41f4b71Sopenharmony_ci   ```bash
644e41f4b71Sopenharmony_ci   # 例:.idl文件为IQuickFixManager.idl
645e41f4b71Sopenharmony_ci   axx_bxx_cxx_proxy.cpp为:quick_fix_manager_proxy.cpp
646e41f4b71Sopenharmony_ci   axx_bxx_cxx_stub.cpp为:quick_fix_manager_stub.cpp
647e41f4b71Sopenharmony_ci   ```
648e41f4b71Sopenharmony_ci
649e41f4b71Sopenharmony_ci   如果需要生成的模板文件名第一个字母为I时,需要在interface命名时在前面加一个I。
650e41f4b71Sopenharmony_ci
651e41f4b71Sopenharmony_ci   ```bash
652e41f4b71Sopenharmony_ci   # 例:生成的模板文件为quick_fix_manager_proxy.cpp时interface的名称应为IQuickFixManager
653e41f4b71Sopenharmony_ci   # .idl文件中的定义
654e41f4b71Sopenharmony_ci   interface OHOS.AAFwk.IQuickFixManager {
655e41f4b71Sopenharmony_ci       void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
656e41f4b71Sopenharmony_ci       void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
657e41f4b71Sopenharmony_ci       void RevokeQuickFix([in] String bundleName);
658e41f4b71Sopenharmony_ci   }
659e41f4b71Sopenharmony_ci   ```
660e41f4b71Sopenharmony_ci
661e41f4b71Sopenharmony_ci   配置hilog,参数log_domainid和log_tag必须成对出现,若只写一个会编译错误。
662e41f4b71Sopenharmony_ci
663e41f4b71Sopenharmony_ci   ```bash
664e41f4b71Sopenharmony_ci   idl_gen_interface("quickfix_manager_interface") {
665e41f4b71Sopenharmony_ci     src_idl = rebase_path("IQuickFixManager.idl")
666e41f4b71Sopenharmony_ci     dst_file = string_join(",", idl_interface_sources)
667e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
668e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
669e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"    #只有一个log_tag,编译会错误,同理只有log_domainid,编译也会错误
670e41f4b71Sopenharmony_ci   }
671e41f4b71Sopenharmony_ci   ```
672e41f4b71Sopenharmony_ci
673e41f4b71Sopenharmony_ci3. 在BUILD.gn中添加模板文件的头文件路径。
674e41f4b71Sopenharmony_ci
675e41f4b71Sopenharmony_ci   只需将“${target_gen_dir}”名添加到现有include_dirs中即可,其它不需要更改。
676e41f4b71Sopenharmony_ci
677e41f4b71Sopenharmony_ci   ```bash
678e41f4b71Sopenharmony_ci   include_dirs = [
679e41f4b71Sopenharmony_ci     "aaa/bbb/ccc",        # 原有头文件路径
680e41f4b71Sopenharmony_ci     "${target_gen_dir}",  # 模板头文件路径
681e41f4b71Sopenharmony_ci   ]
682e41f4b71Sopenharmony_ci   ```
683e41f4b71Sopenharmony_ci
684e41f4b71Sopenharmony_ci4. 在BUILD.gn中添加模板文件.cpp文件路径。
685e41f4b71Sopenharmony_ci
686e41f4b71Sopenharmony_ci   若sources中有axx_bxx_cxx_proxy.cppaxx_bxx_cxx_stub.cpp需要删除,并加上sources += filter_include(output_values, [ "*.cpp" ])。
687e41f4b71Sopenharmony_ci
688e41f4b71Sopenharmony_ci   ```bash
689e41f4b71Sopenharmony_ci   output_values = get_target_outputs(":EEEFFFGGG") # 返回给定目标标签的输出文件列表,替换EEEFFFGGG
690e41f4b71Sopenharmony_ci   sources = [ "axx_bxx_cxx_proxy.cpp" ]  # 需要删除axx_bxx_cxx_proxy.cpp
691e41f4b71Sopenharmony_ci   sources += filter_include(output_values, [ "*.cpp" ]) # filter_include选中符合的列表,直接复制即可
692e41f4b71Sopenharmony_ci   ```
693e41f4b71Sopenharmony_ci
694e41f4b71Sopenharmony_ci5. 在BUILD.gn中添加依赖“EEEFFFGGG”。
695e41f4b71Sopenharmony_ci
696e41f4b71Sopenharmony_ci   ```bash
697e41f4b71Sopenharmony_ci   deps = [
698e41f4b71Sopenharmony_ci       ":EEEFFFGGG",
699e41f4b71Sopenharmony_ci     ]
700e41f4b71Sopenharmony_ci   ```
701e41f4b71Sopenharmony_ci
702e41f4b71Sopenharmony_ci   deps添加的依赖名,必须同idl_gen_interface函数参数名相同。
703e41f4b71Sopenharmony_ci
704e41f4b71Sopenharmony_ci   ```bash
705e41f4b71Sopenharmony_ci   idl_gen_interface("quickfix_manager_interface") {
706e41f4b71Sopenharmony_ci     src_idl = rebase_path("IQuickFixManager.idl")
707e41f4b71Sopenharmony_ci     dst_file = string_join(",", idl_interface_sources)
708e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
709e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
710e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"
711e41f4b71Sopenharmony_ci   }
712e41f4b71Sopenharmony_ci   deps = [
713e41f4b71Sopenharmony_ci    "${ability_runtime_innerkits_path}/app_manager:app_manager",
714e41f4b71Sopenharmony_ci    ":quickfix_manager_interface"]    # idl_gen_interface函数参数名相同
715e41f4b71Sopenharmony_ci   ```
716e41f4b71Sopenharmony_ci
717e41f4b71Sopenharmony_ci6. 在BUILD.gn中添加模板文件的外部依赖。
718e41f4b71Sopenharmony_ci
719e41f4b71Sopenharmony_ci   模板文件的外部依赖需要自己添加到external_deps里。
720e41f4b71Sopenharmony_ci
721e41f4b71Sopenharmony_ci   若之前已存在,不需要重复添加,若重复添加会导致编译错误。
722e41f4b71Sopenharmony_ci
723e41f4b71Sopenharmony_ci   ```bash
724e41f4b71Sopenharmony_ci     external_deps = [
725e41f4b71Sopenharmony_ci     # 模板文件必须的依赖
726e41f4b71Sopenharmony_ci     "c_utils:utils",
727e41f4b71Sopenharmony_ci     # hilog输出必须的依赖
728e41f4b71Sopenharmony_ci     "hilog:libhilog",
729e41f4b71Sopenharmony_ci     # hitrace输出必须的依赖
730e41f4b71Sopenharmony_ci     "hitrace:hitrace_meter",
731e41f4b71Sopenharmony_ci     # 模板文件必须的依赖
732e41f4b71Sopenharmony_ci     "ipc:ipc_core",
733e41f4b71Sopenharmony_ci   ]
734e41f4b71Sopenharmony_ci   ```
735e41f4b71Sopenharmony_ci
736e41f4b71Sopenharmony_ci#### 实例
737e41f4b71Sopenharmony_ci
738e41f4b71Sopenharmony_ci**以应用快速修复服务为例:**
739e41f4b71Sopenharmony_ci
740e41f4b71Sopenharmony_ci1. 创建名为IQuickFixManager.idl文件。
741e41f4b71Sopenharmony_ci
742e41f4b71Sopenharmony_ci   在创建.idl文件时,interface名称必须和.idl文件名相同,否则会在生成代码时出现错误。
743e41f4b71Sopenharmony_ci
744e41f4b71Sopenharmony_ci   创建.idl的文件路径与功能代码BUILD.gn的路径相同。
745e41f4b71Sopenharmony_ci
746e41f4b71Sopenharmony_ci   实例中的位置为:foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/。
747e41f4b71Sopenharmony_ci
748e41f4b71Sopenharmony_ci   ```bash
749e41f4b71Sopenharmony_ci   /*
750e41f4b71Sopenharmony_ci    * Copyright (c) 2023 Huawei Device Co., Ltd.
751e41f4b71Sopenharmony_ci    * Licensed under the Apache License, Version 2.0 (the "License");
752e41f4b71Sopenharmony_ci    * you may not use this file except in compliance with the License.
753e41f4b71Sopenharmony_ci    * You may obtain a copy of the License at
754e41f4b71Sopenharmony_ci    *
755e41f4b71Sopenharmony_ci    *     http://www.apache.org/licenses/LICENSE-2.0
756e41f4b71Sopenharmony_ci    *
757e41f4b71Sopenharmony_ci    * Unless required by applicable law or agreed to in writing, software
758e41f4b71Sopenharmony_ci    * distributed under the License is distributed on an "AS IS" BASIS,
759e41f4b71Sopenharmony_ci    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
760e41f4b71Sopenharmony_ci    * See the License for the specific language governing permissions and
761e41f4b71Sopenharmony_ci    * limitations under the License.
762e41f4b71Sopenharmony_ci    */
763e41f4b71Sopenharmony_ci   
764e41f4b71Sopenharmony_ci   sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo;
765e41f4b71Sopenharmony_ci   interface OHOS.AAFwk.IQuickFixManager {
766e41f4b71Sopenharmony_ci       void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug);
767e41f4b71Sopenharmony_ci       void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
768e41f4b71Sopenharmony_ci       void RevokeQuickFix([in] String bundleName);
769e41f4b71Sopenharmony_ci   }
770e41f4b71Sopenharmony_ci   ```
771e41f4b71Sopenharmony_ci
772e41f4b71Sopenharmony_ci   在创建.idl文件时,需要将返回值为int的函数,修改为void。
773e41f4b71Sopenharmony_ci
774e41f4b71Sopenharmony_ci   ```bash
775e41f4b71Sopenharmony_ci   # 例 quick_fix_manager_client.h中的函数
776e41f4b71Sopenharmony_ci       int32_t ApplyQuickFix(const std::vector<std::string> &quickFixFiles);
777e41f4b71Sopenharmony_ci       int32_t GetApplyedQuickFixInfo(const std::string &bundleName, ApplicationQuickFixInfo &quickFixInfo);
778e41f4b71Sopenharmony_ci       int32_t RevokeQuickFix(const std::string &bundleName);
779e41f4b71Sopenharmony_ci   # .idl文件中的定义
780e41f4b71Sopenharmony_ci   interface OHOS.AAFwk.QuickFixManager {
781e41f4b71Sopenharmony_ci       void ApplyQuickFix([in] String[] quickFixFiles);
782e41f4b71Sopenharmony_ci       void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo);
783e41f4b71Sopenharmony_ci       void RevokeQuickFix([in] String bundleName);
784e41f4b71Sopenharmony_ci   }
785e41f4b71Sopenharmony_ci   ```
786e41f4b71Sopenharmony_ci
787e41f4b71Sopenharmony_ci2. 修改BUILD.gn文件。
788e41f4b71Sopenharmony_ci
789e41f4b71Sopenharmony_ci   ```bash
790e41f4b71Sopenharmony_ci   # Copyright (c) 2023 Huawei Device Co., Ltd.
791e41f4b71Sopenharmony_ci   # Licensed under the Apache License, Version 2.0 (the "License");
792e41f4b71Sopenharmony_ci   # you may not use this file except in compliance with the License.
793e41f4b71Sopenharmony_ci   # You may obtain a copy of the License at
794e41f4b71Sopenharmony_ci   #
795e41f4b71Sopenharmony_ci   #     http://www.apache.org/licenses/LICENSE-2.0
796e41f4b71Sopenharmony_ci   #
797e41f4b71Sopenharmony_ci   # Unless required by applicable law or agreed to in writing, software
798e41f4b71Sopenharmony_ci   # distributed under the License is distributed on an "AS IS" BASIS,
799e41f4b71Sopenharmony_ci   # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
800e41f4b71Sopenharmony_ci   # See the License for the specific language governing permissions and
801e41f4b71Sopenharmony_ci   # limitations under the License.
802e41f4b71Sopenharmony_ci   
803e41f4b71Sopenharmony_ci   import("//build/ohos.gni")
804e41f4b71Sopenharmony_ci   import("//foundation/ability/ability_runtime/ability_runtime.gni")
805e41f4b71Sopenharmony_ci   import("//foundation/ability/idl_tool/idl_config.gni")
806e41f4b71Sopenharmony_ci   
807e41f4b71Sopenharmony_ci   idl_interface_sources = [
808e41f4b71Sopenharmony_ci     "${target_gen_dir}/quick_fix_manager_proxy.cpp",
809e41f4b71Sopenharmony_ci     "${target_gen_dir}/quick_fix_manager_stub.cpp",
810e41f4b71Sopenharmony_ci   ]
811e41f4b71Sopenharmony_ci   
812e41f4b71Sopenharmony_ci   idl_gen_interface("quickfix_manager_interface") {
813e41f4b71Sopenharmony_ci     src_idl = rebase_path("IQuickFixManager.idl")
814e41f4b71Sopenharmony_ci     dst_file = string_join(",", idl_interface_sources)
815e41f4b71Sopenharmony_ci     hitrace = "HITRACE_TAG_ABILITY_MANAGER"
816e41f4b71Sopenharmony_ci     log_domainid = "0xD003900"
817e41f4b71Sopenharmony_ci     log_tag = "QuickFixManagerService"
818e41f4b71Sopenharmony_ci   }
819e41f4b71Sopenharmony_ci   
820e41f4b71Sopenharmony_ci   config("quickfix_config") {
821e41f4b71Sopenharmony_ci     visibility = [ ":*" ]
822e41f4b71Sopenharmony_ci     include_dirs = [
823e41f4b71Sopenharmony_ci       "include",
824e41f4b71Sopenharmony_ci       "${target_gen_dir}",
825e41f4b71Sopenharmony_ci     ]
826e41f4b71Sopenharmony_ci     cflags = []
827e41f4b71Sopenharmony_ci     if (target_cpu == "arm") {
828e41f4b71Sopenharmony_ci       cflags += [ "-DBINDER_IPC_32BIT" ]
829e41f4b71Sopenharmony_ci     }
830e41f4b71Sopenharmony_ci   }
831e41f4b71Sopenharmony_ci   
832e41f4b71Sopenharmony_ci   ohos_shared_library("quickfix_manager") {
833e41f4b71Sopenharmony_ci     configs = [ "${ability_runtime_services_path}/common:common_config" ]
834e41f4b71Sopenharmony_ci     public_configs = [ ":quickfix_config" ]
835e41f4b71Sopenharmony_ci   
836e41f4b71Sopenharmony_ci     output_values = get_target_outputs(":quickfix_manager_interface")
837e41f4b71Sopenharmony_ci     sources = [
838e41f4b71Sopenharmony_ci       "src/quick_fix_error_utils.cpp",
839e41f4b71Sopenharmony_ci       "src/quick_fix_info.cpp",
840e41f4b71Sopenharmony_ci       "src/quick_fix_load_callback.cpp",
841e41f4b71Sopenharmony_ci       "src/quick_fix_manager_client.cpp",
842e41f4b71Sopenharmony_ci       "src/quick_fix_utils.cpp",
843e41f4b71Sopenharmony_ci     ]
844e41f4b71Sopenharmony_ci     sources += filter_include(output_values, [ "*.cpp" ])
845e41f4b71Sopenharmony_ci     defines = [ "AMS_LOG_TAG = \"QuickFixService\"" ]
846e41f4b71Sopenharmony_ci     deps = [
847e41f4b71Sopenharmony_ci       ":quickfix_manager_interface",
848e41f4b71Sopenharmony_ci       "${ability_runtime_innerkits_path}/app_manager:app_manager",
849e41f4b71Sopenharmony_ci     ]
850e41f4b71Sopenharmony_ci   
851e41f4b71Sopenharmony_ci     external_deps = [
852e41f4b71Sopenharmony_ci       "ability_base:want",
853e41f4b71Sopenharmony_ci       "bundle_framework:appexecfwk_base",
854e41f4b71Sopenharmony_ci       "bundle_framework:appexecfwk_core",
855e41f4b71Sopenharmony_ci       "c_utils:utils",
856e41f4b71Sopenharmony_ci       "hilog:libhilog",
857e41f4b71Sopenharmony_ci       "hitrace:hitrace_meter",
858e41f4b71Sopenharmony_ci       "ipc:ipc_single",
859e41f4b71Sopenharmony_ci       "safwk:system_ability_fwk",
860e41f4b71Sopenharmony_ci       "samgr:samgr_proxy",
861e41f4b71Sopenharmony_ci     ]
862e41f4b71Sopenharmony_ci   
863e41f4b71Sopenharmony_ci     innerapi_tags = [ "platformsdk" ]
864e41f4b71Sopenharmony_ci     subsystem_name = "ability"
865e41f4b71Sopenharmony_ci     part_name = "ability_runtime"
866e41f4b71Sopenharmony_ci   }
867e41f4b71Sopenharmony_ci   ```
868e41f4b71Sopenharmony_ci
869e41f4b71Sopenharmony_ci3. 生成模板文件的路径及目录结构。
870e41f4b71Sopenharmony_ci
871e41f4b71Sopenharmony_ci   编译以rk3568为例,实例中生成的模板文件路径为:out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/。
872e41f4b71Sopenharmony_ci
873e41f4b71Sopenharmony_ci   其中foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/为.idl文件所在的相对路径。
874e41f4b71Sopenharmony_ci
875e41f4b71Sopenharmony_ci   生成文件目录结构为:
876e41f4b71Sopenharmony_ci
877e41f4b71Sopenharmony_ci   ```bash
878e41f4b71Sopenharmony_ci   |-- out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/
879e41f4b71Sopenharmony_ci      |-- iquick_fix_manager.h
880e41f4b71Sopenharmony_ci      |-- quick_fix_manager_stub.h
881e41f4b71Sopenharmony_ci      |-- quick_fix_manager_stub.cpp
882e41f4b71Sopenharmony_ci      |-- quick_fix_manager_proxy.h
883e41f4b71Sopenharmony_ci      |-- quick_fix_manager_proxy.cpp
884e41f4b71Sopenharmony_ci   ```
885e41f4b71Sopenharmony_ci
886e41f4b71Sopenharmony_ci
887e41f4b71Sopenharmony_ci## 相关实例
888e41f4b71Sopenharmony_ci
889e41f4b71Sopenharmony_ci针对IDL的使用,有以下相关实例可供参考:
890e41f4b71Sopenharmony_ci
891e41f4b71Sopenharmony_ci- [Ability与ServiceExtensionAbility通信(ArkTS)(Full SDK)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/SystemFeature/IDL/AbilityConnectServiceExtension)