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 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 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.h” 66e41f4b71Sopenharmony_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<T>;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<T> | 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 161e41f4b71Sopenharmony_ci 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.cpp和axx_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.cpp和axx_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)