idl-guidelines.md 19.9 KB
Newer Older
Y
yuyaozhi 已提交
1 2
# OpenHarmony IDL工具规格及使用说明书

W
wusongqing 已提交
3
## IDL接口描述语言简介
Y
yuyaozhi 已提交
4 5
在OpenHarmony中,当客户端和服务器进行IPC通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony IDL(OpenHarmony Interface Definition Language)则是一种定义此类接口的工具。OpenHarmony IDL先把需要传递的对象分解成操作系统能够理解的基本类型,并根据开发者的需要封装跨边界的对象。

Y
yuyaozhi 已提交
6 7
  **图1** IDL接口描述

Y
yuyaozhi 已提交
8 9
![IDL-interface-description](./figures/IDL-interface-description.png)

10
 **OpenHarmony IDL接口描述语言主要用于:** 
Y
yuyaozhi 已提交
11 12 13 14 15

- 声明系统服务对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。

- 声明Ability对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。

Y
yuyaozhi 已提交
16
**图2** IPC/RPC通信模型
Y
yuyaozhi 已提交
17 18 19

![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png)

20
 **使用OpenHarmony IDL接口描述语言声明接口具有以下优点:** 
Y
yuyaozhi 已提交
21 22 23 24 25

- OpenHarmony IDL中是以接口的形式定义服务,可以专注于定义而隐藏实现细节。

- OpenHarmony IDL中定义的接口可以支持跨进程调用或跨设备调用。根据OpenHarmony IDL中的定义生成的信息或代码可以简化跨进程或跨设备调用接口的实现。

W
wusongqing 已提交
26
## IDL接口描述语言构成
Y
yuyaozhi 已提交
27

W
wusongqing 已提交
28
### 数据类型
Y
yuyaozhi 已提交
29

W
wusongqing 已提交
30
#### 基础数据类型
Y
yuyaozhi 已提交
31
| IDL基本数据类型 | C++基本数据类型 | TS基本数据类型 |
32 33 34 35 36 37 38 39 40 41
|   --------    |  --------     | --------     |
|void           | void          | void         |
|boolean        | bool          | boolean      |
|byte           | int8_t        | number       |
|short          | int16_t       | number       |
|int            | int32_t       | number       |
|long           | int64_t       | number       |
|float          | float         | number       |
|double         | double        | number       |
|String         | std::string   | string       |
Y
yuyaozhi 已提交
42

Y
yuyaozhi 已提交
43
IDL支持的基本数据类型及其映射到C++、TS上的数据类型的对应关系如上表所示。
Y
yuyaozhi 已提交
44

W
wusongqing 已提交
45
#### sequenceable数据类型
L
liqiang 已提交
46
sequenceable数据类型是指使用“sequenceable”关键字声明的数据,表明该数据类型可以被序列化进行跨进程或跨设备传递。sequenceable在C++与TS中声明方式存在一定差异。
Y
yuyaozhi 已提交
47 48 49

在C++中sequenceable数据类型的声明放在文件的头部,以“sequenceable includedir..namespace.typename”的形式声明。具体而言。声明可以有如下三个形式:

50
```cpp
Y
yuyaozhi 已提交
51 52 53 54
sequenceable includedir..namespace.typename
sequenceable includedir...typename
sequenceable namespace.typename
```
55

Y
yuyaozhi 已提交
56
其中,includedir表示该数据类型头文件所在目录,includedir中以“.”作为分隔符。namespace表示该数据类型所在命名空间,namespace中同样以“.”作为分隔符。typename表示数据类型,数据类型中不能包含非英文字符类型的其他符号。includedir与namespace之间通过“..”分割,如果类型声明的表达式中不包含“..”,除去最后一个typename之外的字符都会被解析为命名空间。例如:
57 58

```cpp
Y
yuyaozhi 已提交
59 60
sequenceable a.b..C.D
```
61

62
 上述声明在生成的的C++头文件中将被解析为如下代码:
63 64

```cpp
Y
yuyaozhi 已提交
65 66 67
#include  “a/b/d.h”
using C::D;
```
68

Y
yuyaozhi 已提交
69 70
TS声明放在文件的头部,以 “sequenceable namespace.typename;”的形式声明。具体而言,声明可以有如下形式:

71
```ts
Y
yuyaozhi 已提交
72 73 74
sequenceable idl.MySequenceable
```

Y
yuyaozhi 已提交
75
其中,namespace是该类型所属的命名空间,typename是类型名。MySequenceable类型表示可以通过Parcel进行跨进程传递。sequenceable数据类型并不在OpenHarmony IDL文件中定义,而是定义在.ts文件中。因此,OpenHarmony IDL工具将根据声明在生成的.ts代码文件中加入如下语句:
Y
yuyaozhi 已提交
76

77
```ts
Y
yuyaozhi 已提交
78
import MySequenceable from "./my_sequenceable"
Y
yuyaozhi 已提交
79 80 81 82
```

需要注意的是,IDL并不负责该类型的代码实现,仅仅按照指定的形式引入该头文件或import指定模块,并使用该类型,因此开发者需要自行保证引入目录、命名空间及类型的正确性。

W
wusongqing 已提交
83
#### 接口类型
84
 接口类型是指OpenHarmony IDL文件中定义的接口。对于当前IDL文件中定义的接口,可以直接使用它作为方法参数类型或返回值类型。而在其它OpenHarmony IDL文件中定义的接口,则需要在文件的头部进行前置声明。 
Y
yuyaozhi 已提交
85

86
 C++中声明的形式与sequenceable类型相似,具体而言可以有如下形式: 
Y
yuyaozhi 已提交
87

88
```cpp
Y
yuyaozhi 已提交
89 90 91
interface includedir..namespace.typename
```

92
 TS中声明的形式,具体而言可以有如下形式: 
Y
yuyaozhi 已提交
93

94
```ts
Y
yuyaozhi 已提交
95 96 97 98 99
interface namespace.interfacename
```

其中,namespace是该接口所属的命名空间,interfacename是接口名。例如:“interface OHOS.IIdlTestObserver;”声明了在其他OpenHarmony IDL文件定义的IIdlTestObserver接口,该接口可以作为当前定义中方法的参数类型或返回值类型使用。OpenHarmony IDL工具将根据该声明在生成的TS代码文件中加入如下语句:

100
```ts
Y
yuyaozhi 已提交
101 102 103
import IIdlTestObserver from "./i_idl_test_observer"
```

W
wusongqing 已提交
104
#### 数组类型
105
数组类型使用“T[]”表示,其中T可以是基本数据类型、sequenceable数据类型、interface类型和数组类型。该类型在C++生成代码中将被生成为std::vector<T>类型。
Y
yuyaozhi 已提交
106 107
OpenHarmony IDL数组数据类型与TS数据类型、C++数据类型的对应关系如下表所示:

108 109 110
|OpenHarmony IDL数据类型  | C++数据类型           | TS数据类型     |
|   -------              |  --------            |  --------    |
|T[]                     | std::vector<T> | T[]          |
Y
yuyaozhi 已提交
111

W
wusongqing 已提交
112
#### 容器类型
Y
yuyaozhi 已提交
113 114 115 116 117 118 119 120 121
IDL支持两种容器类型,即List和Map。其中List类型容器的用法为List&lt;T&gt;;Map容器的用法为Map<KT,VT>,其中T、KT、VT为基本数据类型、sequenceable类型、interface类型、数组类型或容器类型。

List类型在C++代码中被映射为std::list,Map容器被映射为std::map。

List类型在TS代码中不支持,Map容器被映射为Map。

OpenHarmony IDL容器数据类型与Ts数据类型、C++数据类型的对应关系如下表所示:

|OpenHarmony IDL数据类型  | C++数据类型       | TS数据类型     |
122 123 124
|   --------             |  --------        |  -------     |
|List&lt;T&gt;           | std::list        | 不支持        |
|Map<KT,VT>              | std::map         | Map          |
Y
yuyaozhi 已提交
125 126


W
wusongqing 已提交
127
### IDL文件编写规范
Y
yuyaozhi 已提交
128
一个idl文件只能定义一个interface类型,且该interface名称必须和文件名相同。idl文件的接口定义使用BNF范式描述,其基本定义的形式如下:
129

Y
yuyaozhi 已提交
130 131 132
```
[<*interface_attr_declaration*>]interface<*interface_name_with_namespace*>{<*method_declaration*>}
```
133

Y
yuyaozhi 已提交
134
其中,<*interface_attr_declaration*>表示接口属性声明。当前仅支持“oneway”属性,表示该接口中的接口都是单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。接口名需要包含完整的接口头文件目录及命名空间,且必须包含方法声明,不允许出现空接口。
Y
yuyaozhi 已提交
135
接口内的方法声明形式为:
136

Y
yuyaozhi 已提交
137
```
Y
yuyaozhi 已提交
138
[<*method_attr_declaration*>]<*result_type*><*method_declaration*>
Y
yuyaozhi 已提交
139
```
140

Y
yuyaozhi 已提交
141
其中,<*method_attr_declaration*>表示接口属性说明。当前仅支持“oneway”属性,表示该方法为单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。<*result_type*>为返回值类型,<*method_declaration*>是方法名和各个参数声明。
Y
yuyaozhi 已提交
142
参数声明的形式为:
143

Y
yuyaozhi 已提交
144
```
Y
yuyaozhi 已提交
145
[<*formal_param_attr*>]<*type*><*identifier*>
Y
yuyaozhi 已提交
146
```
147

Y
yuyaozhi 已提交
148 149
其中<*formal_param_attr*>的值为“in”,“out”,“inout”,分别表示该参数是输入参数,输出参数或输入输出参数。需要注意的是,如果一个方法被声明为oneway,则该方法不允许有输出类型的参数(及输入输出类型)和返回值。

W
wusongqing 已提交
150
## 开发步骤
Y
yuyaozhi 已提交
151

C
chenyuyan 已提交
152
### IDL工具的获取
C
chenyuyan 已提交
153
首先,打开DevEco Studio—>Tools—>SDK Manager,查看OpenHarmony SDK的本地安装路径,此处以DevEco Studio 3.0.0.993版本为例,查看方式如下图所示。
C
chenyuyan 已提交
154 155 156
![SDKpath](./figures/SDKpath.png)
![SDKpath](./figures/SDKpath2.png)

C
chenyuyan 已提交
157
进入对应路径后,查看toolchains->3.x.x.x(对应版本号命名文件夹)下是否存在idl工具的可执行文件。
Y
yuyaozhi 已提交
158

159 160 161
> **注意**:
> 
> 请保证使用最新版的SDK,版本老旧可能导致部分语句报错。
Y
yuyaozhi 已提交
162

163
若不存在,可对应版本前往[docs仓版本目录](../../release-notes)下载SDK包,以[3.2Beta3版本](../../release-notes/OpenHarmony-v3.2-beta3.md)为例,可通过镜像站点获取。
C
chenyuyan 已提交
164

Z
zengyawen 已提交
165
关于如何替换DevEco Studio的SDK包具体操作,参考[full-SDK替换指南](../faqs/full-sdk-compile-guide.md)中的替换方法。
C
chenyuyan 已提交
166 167 168

得到idl工具的可执行文件后,根据具体场景进行后续开发步骤。

C
chenyuyan 已提交
169
### TS开发步骤
Y
yuyaozhi 已提交
170

W
wusongqing 已提交
171
#### 创建.idl文件
Y
yuyaozhi 已提交
172

C
chenyuyan 已提交
173 174 175
 开发者可以使用TS编程语言构建.idl文件。

 例如,此处构建一个名为IIdlTestService.idl的文件,文件内具体内容如下:  
Y
yuyaozhi 已提交
176

177
```cpp
Y
yuyaozhi 已提交
178 179 180
  interface OHOS.IIdlTestService {
      int TestIntTransaction([in] int data);
      void TestStringTransaction([in] String data);
181 182
      void TestMapTransaction([in] Map<int, int> data);
      int TestArrayTransaction([in] String[] data);
Y
yuyaozhi 已提交
183 184 185
  }
```

C
chenyuyan 已提交
186
在idl的可执行文件所在文件夹下执行命令 `idl -gen-ts -d dir -c dir/IIdlTestService.idl`
Y
yuyaozhi 已提交
187

C
chenyuyan 已提交
188
-d后的dir为目标输出目录,以输出文件夹名为IIdlTestServiceTs为例,在idl可执行文件所在目录下执行`idl -gen-ts -d IIdlTestServiceTs -c IIdlTestServiceTs/IIdlTestService.idl`,将会在执行环境的dir目录(即IIdlTestServiceTs目录)中生成接口文件、Stub文件、Proxy文件。
Y
yuyaozhi 已提交
189

C
chenyuyan 已提交
190
> **注意**:生成的接口类文件名称和.idl文件名称保持一致,否则会生成代码时会出现错误。
Y
yuyaozhi 已提交
191

C
chenyuyan 已提交
192
以名为`IIdlTestService.idl`的.idl文件、目标输出文件夹为IIdlTestServiceTs为例,其目录结构应类似于:
Y
yuyaozhi 已提交
193 194

```
C
chenyuyan 已提交
195 196 197 198 199 200
├── IIdlTestServiceTs  # idl代码输出文件夹
│   ├── i_idl_test_service.ts  # 生成文件
│   ├── idl_test_service_proxy.ts  # 生成文件
│   ├── idl_test_service_stub.ts  # 生成文件
│   └── IIdlTestService.idl  # 构造的.idl文件
└── idl.exe  # idl的可执行文件
Y
yuyaozhi 已提交
201 202
```

W
wusongqing 已提交
203
#### 服务端公开接口
Y
yuyaozhi 已提交
204

205
OpenHarmony IDL工具生成的Stub类是接口类的抽象实现,并且会声明.idl文件中的所有方法。 
Y
yuyaozhi 已提交
206

207
```ts
Y
yuyaozhi 已提交
208 209
import {testIntTransactionCallback} from "./i_idl_test_service";
import {testStringTransactionCallback} from "./i_idl_test_service";
210 211
import {testMapTransactionCallback} from "./i_idl_test_service";
import {testArrayTransactionCallback} from "./i_idl_test_service";
Y
yuyaozhi 已提交
212 213 214 215 216 217 218 219
import IIdlTestService from "./i_idl_test_service";
import rpc from "@ohos.rpc";

export default class IdlTestServiceStub extends rpc.RemoteObject implements IIdlTestService {
    constructor(des: string) {
        super(des);
    }
    
L
update  
liuliu 已提交
220 221
    async onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence,
        option: rpc.MessageOption): Promise<boolean> {
222
        console.log("onRemoteMessageRequest called, code = " + code);
L
liuliu 已提交
223 224
        if (code == IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION) {
            let _data = data.readInt();
L
update  
liuliu 已提交
225
            this.testIntTransaction(_data, (errCode: number, returnValue: number) => {
L
liuliu 已提交
226 227 228
                reply.writeInt(errCode);
                if (errCode == 0) {
                    reply.writeInt(returnValue);
229
                }
L
liuliu 已提交
230 231 232 233
            });
            return true;
        } else if (code == IdlTestServiceStub.COMMAND_TEST_STRING_TRANSACTION) {
            let _data = data.readString();
L
update  
liuliu 已提交
234
            this.testStringTransaction(_data, (errCode: number) => {
L
liuliu 已提交
235 236 237 238 239 240 241 242 243 244
                reply.writeInt(errCode);
            });
            return true;
        } else if (code == IdlTestServiceStub.COMMAND_TEST_MAP_TRANSACTION) {
            let _data: Map<number, number> = new Map();
            let _dataSize = data.readInt();
            for (let i = 0; i < _dataSize; ++i) {
                let key = data.readInt();
                let value = data.readInt();
                _data.set(key, value);
Y
yuyaozhi 已提交
245
            }
L
update  
liuliu 已提交
246
            this.testMapTransaction(_data, (errCode: number) => {
L
liuliu 已提交
247 248 249 250 251
                reply.writeInt(errCode);
            });
            return true;
        } else if (code == IdlTestServiceStub.COMMAND_TEST_ARRAY_TRANSACTION) {
            let _data = data.readStringArray();
L
update  
liuliu 已提交
252
            this.testArrayTransaction(_data, (errCode: number, returnValue: number) => {
L
liuliu 已提交
253 254 255 256 257 258 259 260
                reply.writeInt(errCode);
                if (errCode == 0) {
                    reply.writeInt(returnValue);
                }
            });
            return true;
        } else {
            console.log("invalid request code" + code);
Y
yuyaozhi 已提交
261 262 263 264 265 266
        }
        return false;
    }
    
    testIntTransaction(data: number, callback: testIntTransactionCallback): void{}
    testStringTransaction(data: string, callback: testStringTransactionCallback): void{}
267 268
    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void{}
    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void{}
Y
yuyaozhi 已提交
269 270 271

    static readonly COMMAND_TEST_INT_TRANSACTION = 1;
    static readonly COMMAND_TEST_STRING_TRANSACTION = 2;
272 273
    static readonly COMMAND_TEST_MAP_TRANSACTION = 3;
    static readonly COMMAND_TEST_ARRAY_TRANSACTION = 4;
Y
yuyaozhi 已提交
274 275 276
}
```

277
开发者需要继承.idl文件中定义的接口类并实现其中的方法。在本示例中,我们继承了IdlTestServiceStub接口类并实现了其中的testIntTransaction、testStringTransaction、testMapTransaction和testArrayTransaction方法。具体的示例代码如下:
Y
yuyaozhi 已提交
278

279
```ts
Y
yuyaozhi 已提交
280 281
import {testIntTransactionCallback} from "./i_idl_test_service"
import {testStringTransactionCallback} from "./i_idl_test_service"
282 283
import {testMapTransactionCallback} from "./i_idl_test_service";
import {testArrayTransactionCallback} from "./i_idl_test_service";
Y
yuyaozhi 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296
import IdlTestServiceStub from "./idl_test_service_stub"


class IdlTestImp extends IdlTestServiceStub {

    testIntTransaction(data: number, callback: testIntTransactionCallback): void
    {
        callback(0, data + 1);
    }
    testStringTransaction(data: string, callback: testStringTransactionCallback): void
    {
        callback(0);
    }
297 298 299 300 301 302 303 304
    testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void
    {
        callback(0);
    }
    testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void
    {
        callback(0, 1);
    }
Y
yuyaozhi 已提交
305 306 307 308 309
}
```

在服务实现接口后,需要向客户端公开该接口,以便客户端进程绑定。如果开发者的服务要公开该接口,请扩展Ability并实现onConnect()从而返回IRemoteObject,以便客户端能与服务进程交互。服务端向客户端公开IRemoteAbility接口的代码示例如下:

310
```ts
L
update  
liuliu 已提交
311 312 313 314
import Want from '@ohos.app.ability.Want';
import rpc from "@ohos.rpc";

export default class ServiceAbility {
Y
yuyaozhi 已提交
315 316
    onStart() {
        console.info('ServiceAbility onStart');
L
update  
liuliu 已提交
317
    };
Y
yuyaozhi 已提交
318 319
    onStop() {
        console.info('ServiceAbility onStop');
L
update  
liuliu 已提交
320 321
    };
    onCommand(want: Want, startId: number) {
Y
yuyaozhi 已提交
322
        console.info('ServiceAbility onCommand');
L
update  
liuliu 已提交
323 324
    };
    onConnect(want: Want) {
Y
yuyaozhi 已提交
325 326 327 328 329 330
        console.info('ServiceAbility onConnect');
        try {
            console.log('ServiceAbility want:' + typeof(want));
            console.log('ServiceAbility want:' + JSON.stringify(want));
            console.log('ServiceAbility want name:' + want.bundleName)
        } catch(err) {
F
fangJinliang1 已提交
331
            console.log('ServiceAbility error:' + err)
Y
yuyaozhi 已提交
332 333
        }
        console.info('ServiceAbility onConnect end');
L
update  
liuliu 已提交
334 335 336
        return new IdlTestImp('connect') as rpc.RemoteObject;
    };
    onDisconnect(want: Want) {
Y
yuyaozhi 已提交
337 338 339 340 341 342
        console.info('ServiceAbility onDisconnect');
        console.info('ServiceAbility want:' + JSON.stringify(want));
    }
};
```

W
wusongqing 已提交
343
#### 客户端调用IPC方法
Y
yuyaozhi 已提交
344

Y
yuyaozhi 已提交
345
客户端调用connectServiceExtensionAbility()以连接服务时,客户端的onAbilityConnectDone中的onConnect回调会接收服务的onConnect()方法返回的IRemoteObject实例。由于客户端和服务在不同应用内,所以客户端应用的目录内必须包含.idl文件(SDK工具会自动生成Proxy代理类)的副本。客户端的onAbilityConnectDone中的onConnect回调会接收服务的onConnect()方法返回的IRemoteObject实例,使用IRemoteObject创建IdlTestServiceProxy类的实例对象testProxy,然后调用相关IPC方法。示例代码如下:
Y
yuyaozhi 已提交
346

347
```ts
L
update  
liuliu 已提交
348 349
import common from '@ohos.app.ability.common';
import Want from '@ohos.app.ability.Want';
Y
yuyaozhi 已提交
350 351 352 353
import IdlTestServiceProxy from './idl_test_service_proxy'

function callbackTestIntTransaction(result: number, ret: number): void {
  if (result == 0 && ret == 124) {
F
fangJinliang1 已提交
354
    console.log('case 1 success');
Y
yuyaozhi 已提交
355 356 357 358 359
  }
}

function callbackTestStringTransaction(result: number): void {
  if (result == 0) {
F
fangJinliang1 已提交
360
    console.log('case 2 success');
Y
yuyaozhi 已提交
361 362 363
  }
}

364 365 366 367 368 369 370 371 372 373 374 375
function callbackTestMapTransaction(result: number): void {
  if (result == 0) {
    console.log('case 3 success');
  }
}

function callbackTestArrayTransaction(result: number, ret: number): void {
  if (result == 0 && ret == 124) {
    console.log('case 4 success');
  }
}

L
update  
liuliu 已提交
376 377 378 379
let onAbilityConnectDone: common.ConnectOptions = {
  onConnect: (elementName, proxy) => {
    let testProxy: IdlTestServiceProxy = new IdlTestServiceProxy(proxy);
    let testMap: Map<number, number> = new Map();
380 381
    testMap.set(1, 1);
    testMap.set(1, 2);
Y
yuyaozhi 已提交
382 383
    testProxy.testIntTransaction(123, callbackTestIntTransaction);
    testProxy.testStringTransaction('hello', callbackTestStringTransaction);
384 385
    testProxy.testMapTransaction(testMap, callbackTestMapTransaction);
    testProxy.testArrayTransaction(['1','2'], callbackTestMapTransaction);
Y
yuyaozhi 已提交
386
  },
L
update  
liuliu 已提交
387
  onDisconnect: (elementName) => {
F
fangJinliang1 已提交
388
    console.log('onDisconnectService onDisconnect');
Y
yuyaozhi 已提交
389
  },
L
update  
liuliu 已提交
390
  onFailed: (code) => {
F
fangJinliang1 已提交
391
    console.log('onDisconnectService onFailed');
Y
yuyaozhi 已提交
392 393 394
  }
};

L
update  
liuliu 已提交
395 396
let context: common.UIAbilityContext = this.context;

Y
yuyaozhi 已提交
397
function connectAbility(): void {
L
update  
liuliu 已提交
398
    let want: Want = {
F
fangJinliang1 已提交
399 400
        bundleName: 'com.example.myapplicationidl',
        abilityName: 'com.example.myapplicationidl.ServiceAbility'
Y
yuyaozhi 已提交
401 402
    };
    let connectionId = -1;
L
update  
liuliu 已提交
403
    connectionId = context.connectServiceExtensionAbility(want, onAbilityConnectDone);
Y
yuyaozhi 已提交
404 405 406 407 408
}


```

W
wusongqing 已提交
409
#### IPC传递sequenceable对象
Y
yuyaozhi 已提交
410 411 412

开发者可以通过 IPC 接口,将某个类从一个进程发送至另一个进程。但是,必须确保 IPC 通道的另一端可使用该类的代码,并且该类必须支持marshalling和unmarshalling方法。OpenHarmony 需要通过该marshalling和unmarshalling方法将对象序列化和反序列化成各进程能识别的对象。

413
 **如需创建支持sequenceable 类型数据,开发者必须执行以下操作:** 
Y
yuyaozhi 已提交
414 415 416 417 418 419

1. 实现marshalling方法,它会获取对象的当前状态并将其序列化后写入Parcel。
2. 实现unmarshalling方法,它会从Parcel中反序列化出对象。

MySequenceable类的代码示例如下:

420
```ts
Y
yuyaozhi 已提交
421 422 423 424 425 426 427 428 429 430 431 432
import rpc from '@ohos.rpc';
export default class MySequenceable {
    constructor(num: number, str: string) {
        this.num = num;
        this.str = str;
    }
    getNum() : number {
        return this.num;
    }
    getString() : string {
        return this.str;
    }
L
update  
liuliu 已提交
433
    marshalling(messageParcel: rpc.MessageSequence) {
Y
yuyaozhi 已提交
434 435 436 437
        messageParcel.writeInt(this.num);
        messageParcel.writeString(this.str);
        return true;
    }
L
update  
liuliu 已提交
438
    unmarshalling(messageParcel: rpc.MessageSequence) {
Y
yuyaozhi 已提交
439 440 441 442
        this.num = messageParcel.readInt();
        this.str = messageParcel.readString();
        return true;
    }
L
update  
liuliu 已提交
443 444
    private num: number;
    private str: string;
Y
yuyaozhi 已提交
445 446
}
```
447 448 449 450 451 452

## 相关实例

针对IDL的使用,有以下相关实例可供参考:

- [Ability与ServiceExtensionAbility通信(ArkTS)(Full SDK)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/IDL/AbilityConnectServiceExtension)