From 365863d1de3b9bf503c81c15a15897de1933cd5e Mon Sep 17 00:00:00 2001 From: yuyaozhi Date: Wed, 20 Apr 2022 14:51:44 +0800 Subject: [PATCH] Add IDL docunment of ability Signed-off-by: yuyaozhi --- ...50\350\257\264\346\230\216\344\271\246.md" | 674 ++++++++++++++++++ .../IDL/figures/IDL-interface-description.png | Bin 0 -> 31975 bytes .../figures/IPC-RPC-communication-model.png | Bin 0 -> 16183 bytes 3 files changed, 674 insertions(+) create mode 100644 "zh-cn/application-dev/IDL/OpenHarmony IDL\345\267\245\345\205\267\350\247\204\346\240\274\345\217\212\344\275\277\347\224\250\350\257\264\346\230\216\344\271\246.md" create mode 100644 zh-cn/application-dev/IDL/figures/IDL-interface-description.png create mode 100644 zh-cn/application-dev/IDL/figures/IPC-RPC-communication-model.png diff --git "a/zh-cn/application-dev/IDL/OpenHarmony IDL\345\267\245\345\205\267\350\247\204\346\240\274\345\217\212\344\275\277\347\224\250\350\257\264\346\230\216\344\271\246.md" "b/zh-cn/application-dev/IDL/OpenHarmony IDL\345\267\245\345\205\267\350\247\204\346\240\274\345\217\212\344\275\277\347\224\250\350\257\264\346\230\216\344\271\246.md" new file mode 100644 index 0000000000..3602fb8cb6 --- /dev/null +++ "b/zh-cn/application-dev/IDL/OpenHarmony IDL\345\267\245\345\205\267\350\247\204\346\240\274\345\217\212\344\275\277\347\224\250\350\257\264\346\230\216\344\271\246.md" @@ -0,0 +1,674 @@ +# OpenHarmony IDL工具规格及使用说明书 + +## 1. IDL接口描述语言简介 +在OpenHarmony中,当客户端和服务器进行IPC通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony IDL(OpenHarmony Interface Definition Language)则是一种定义此类接口的工具。OpenHarmony IDL先把需要传递的对象分解成操作系统能够理解的基本类型,并根据开发者的需要封装跨边界的对象。 + +![IDL-interface-description](./figures/IDL-interface-description.png) + +OpenHarmony IDL接口描述语言主要用于: + +- 声明系统服务对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。 + +- 声明Ability对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。 + + **图2** IPC/RPC通信模型 + +![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png) + +使用OpenHarmony IDL接口描述语言声明接口具有以下优点: + +- OpenHarmony IDL中是以接口的形式定义服务,可以专注于定义而隐藏实现细节。 + +- OpenHarmony IDL中定义的接口可以支持跨进程调用或跨设备调用。根据OpenHarmony IDL中的定义生成的信息或代码可以简化跨进程或跨设备调用接口的实现。 + +## 2. IDL接口描述语言构成 + +### 2.1 数据类型 + +#### 2.1.1 基础数据类型 + +| IDL基本数据类型 | C++基本数据类型 | TS基本数据类型 | +| -------- | -------- | -------- | +|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 | + +idl支持的基本数据类型及其映射到C++,TS上的数据类型的对应关系如上表所示。 + +#### 2.1.2 sequenceable数据类型 +sequenceable数据类型是指使用“sequenceable”关键字声明的数据,表面该数据类型可以被序列化进行跨进程或跨设备传递。sequenceable在C++与TS中声明方式存在一定差异。 + +在C++中sequenceable数据类型的声明放在文件的头部,以“sequenceable includedir..namespace.typename”的形式声明。具体而言。声明可以有如下三个形式: + +``` +sequenceable includedir..namespace.typename +sequenceable includedir...typename +sequenceable namespace.typename +``` +其中,includedir表示该数据类型头文件所在目录,includedir中以“.”作为分隔符。namespace表示该数据类型所在命名空间,namespace中同样以“.”作为分隔符。typename表示数据类型,数据类型中不能包含非英文字符类型的其他符号。includedir与namespace之间通过“..”分割,如果类型声明的表达式中不包含“..”,除去最后一个typename之外的字符都会被解析为命名空间。例如: +``` +sequenceable a.b..C.D +``` +上述声明在生成的的C++头文件中将被解析为如下代码: +``` +#include “a/b/d.h” +using C::D; +``` +TS声明放在文件的头部,以 “sequenceable namespace.typename;”的形式声明。具体而言,声明可以有如下形式: + +``` +sequenceable idl.MySequenceable +``` + +其中,namespace是该类型所属的命名空间,typename是类型名。MySequenceable类型表示可以通过Parcel进行跨进程传递。Sequenceable数据类型并不在OpenHarmony IDL文件中定义,而是定义在.ts文件中。因此,OpenHarmony IDL工具将根据声明在生成的.ts代码文件中加入如下语句: + +``` +import MySequenceable from "./mysequenceable" +``` + +需要注意的是,IDL并不负责该类型的代码实现,仅仅按照指定的形式引入该头文件或import指定模块,并使用该类型,因此开发者需要自行保证引入目录、命名空间及类型的正确性。 + +#### 2.1.3 接口类型 +接口类型是指OpenHarmony IDL文件中定义的接口。对于当前IDL文件中定义的接口,可以直接使用它作为方法参数类型或返回值类型。而在其它OpenHarmony IDL文件中定义的接口,则需要在文件的头部进行前置声明。 + +C++中声明的形式与sequenceable类型相似,具体而言可以有如下形式: + +``` +interface includedir..namespace.typename +``` + +TS中声明的形式,具体而言可以有如下形式: + +``` +interface namespace.interfacename +``` + +其中,namespace是该接口所属的命名空间,interfacename是接口名。例如:“interface OHOS.IIdlTestObserver;”声明了在其他OpenHarmony IDL文件定义的IIdlTestObserver接口,该接口可以作为当前定义中方法的参数类型或返回值类型使用。OpenHarmony IDL工具将根据该声明在生成的TS代码文件中加入如下语句: + +``` +import IIdlTestObserver from "./i_idl_test_observer" +``` + +#### 2.1.4 数组类型 +数组类型使用“T[]”表示,其中T可以是基本数据类型、sequenceable数据类型、interface类型和数据类型。该类型在C++生成代码中将被生成为std::vector<T>类型。 +OpenHarmony IDL数组数据类型与TS数据类型、C++数据类型的对应关系如下表所示: + +|OpenHarmony IDL数据类型 | C++数据类型 | TS数据类型 | +| -------- | -------- | -------- | +|T[] | std::vector<T> | T[] | + +#### 2.1.5 容器类型 +IDL支持两种容器类型,即List和Map。其中List类型容器的用法为List<T>;Map容器的用法为Map,其中T、KT、VT为基本数据类型、sequenceable类型、interface类型、数组类型或容器类型。 + +List类型在C++代码中被映射为std::list,Map容器被映射为std::map。 + +List类型在TS代码中不支持,Map容器被映射为Map。 + +OpenHarmony IDL容器数据类型与Ts数据类型、C++数据类型的对应关系如下表所示: + +|OpenHarmony IDL数据类型 | C++数据类型 | TS数据类型 | +| -------- | -------- | -------- | +|List<T> | std::list | 不支持 | +|Map | std::map | Map | + + +### 2.2 IDL文件编写规范 +一个idl文件只能定义一个interface类型,且该interface名称必须和文件名相同。idl文件的接口定义使用BNF范式描述,其基本定义的形式如下: +``` +[<*interface_attr_declaration*>]interface<*interface_name_with_namespace*>{<*method_declaration*>} +``` +其中,<*interface_attr_declaration*>表示接口属性声明。当前仅支持“oneway”属性表示该接口中的接口都是单向方法,即调用方法后不用等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。接口名需要包含完整的接口头文件目录及命名空间,且必须包含方法声明,不允许出现空接口。 +接口内的方法声明形式为: +``` +/[<*method_attr_declaration*>]<*result_type*><*method_declaration*> +``` +其中,<*method_attr_declaration*>表示接口属性说明。当前仅支持“oneway”属性表示该方法为单向方法,即调用方法后不在等待该方法执行即可返回。这个属性为可选项,如果未声明该属性,则默认为同步调用方法。<*result_type*>为返回值类型,<*method_declaration*>是方法名和各个参数声明。 +参数声明的形式为: +``` +[<**formal_param_attr*>]<*type*><*identifier*> +``` +其中<*formal_param_attr*>的值为“in”,“out”,“inout”,分别表示该参数是输入参数,输出参数或输入输出参数。需要注意的是,如果一个方法被声明为oneway,则该方法不允许有输出类型的参数(及输入输出类型)和返回值。 + +## 3.开发步骤 + +### 3.1 C++开发步骤 + +#### 3.1.1 创建.idl文件 + + 开发者可以使用C++编程语言构建.idl文件。.idl示例如下: + +``` + interface OHOS.IIdlTestService { + int TestIntTransaction([in] int data); + void TestStringTransaction([in] String data); + } +``` + +使用者通过执行命令 “./idl -gen-cpp -d dir -c dir/iTest.idl” (-d为输出目录)在执行环境的dir/iTest.idl/目录中生成接口文件、Stub文件、Proxy文件。生成的接口类文件名称和.idl文件名称保持一致,区别在于其使用.h和.cpp扩展名。例如,IIdlTestService. idl 生成的文件名是 i_idl_test_service.h、idl_test_service_proxy.h、idl_test_service_stub.h、idl_test_service_proxy.cpp、idl_test_service_stub.cpp。 + +#### 3.1.2 服务端公开接口 + + OpenHarmony IDL工具生成的Stub类是接口类的抽象实现,并且会声明.idl文件中的所有方法。 + +``` +#ifndef OHOS_IDLTESTSERVICESTUB_H +#define OHOS_IDLTESTSERVICESTUB_H +#include +#include "iidl_test_service.h" + +namespace OHOS { +class IdlTestServiceStub : public IRemoteStub { +public: + int OnRemoteRequest( + /* [in] */ uint32_t code, + /* [in] */ MessageParcel& data, + /* [out] */ MessageParcel& reply, + /* [in] */ MessageOption& option) override; + +private: + static constexpr int COMMAND_TEST_INT_TRANSACTION = MIN_TRANSACTION_ID + 0; + static constexpr int COMMAND_TEST_STRING_TRANSACTION = MIN_TRANSACTION_ID + 1; +}; +} // namespace OHOS +#endif // OHOS_IDLTESTSERVICESTUB_H +``` + +开发者需要继承.idl文件中定义的接口类并实现其中的方法。在本示例中,我们继承了IdlTestServiceStub接口类并实现了其中的TestIntTransaction和TestStringTransaction方法。具体的示例代码如下: + +``` +#include "idl_test_service_stub.h" + +namespace OHOS { +int IdlTest ::OnRemoteRequest( + /* [in] */ uint32_t code, + /* [in] */ MessageParcel& data, + /* [out] */ MessageParcel& reply, + /* [in] */ MessageOption& option) +{ + if (data.ReadInterfaceToken() != GetDescriptor()) { + return ERR_TRANSACTION_FAILED; + } + switch (code) { + case COMMAND_TEST_INT_TRANSACTION: { + int _data = data.ReadInt32(); + int result; + ErrCode ec = TestIntTransaction(_data, result); + reply.WriteInt32(ec); + if (SUCCEEDED(ec)) { + reply.WriteInt32(result); + } + return ERR_NONE; + } + case COMMAND_TEST_STRING_TRANSACTION: { + std::string _data = Str16ToStr8(data.ReadString16()); + ErrCode ec = TestStringTransaction(_data); + reply.WriteInt32(ec); + return ERR_NONE; + } + default: + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + + return ERR_TRANSACTION_FAILED; +} +} +``` + +在服务实现接口后,需要向客户端公开该接口,以便客户端进程绑定。如果开发者的服务要公开该接口,请扩展Ability并实现onConnect()从而返回IRemoteObject,以便客户端能与服务进程交互。服务端向客户端公开IRemoteAbility接口的代码示例如下: + +``` +#include "idl_test_service_proxy.h" + +namespace OHOS { +ErrCode IdlTestServiceProxy::TestIntTransaction( + /* [in] */ int _data, + /* [out] */ int& result) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + return ERR_INVALID_VALUE; + } + + data.WriteInt32(_data); + + if (Remote() == nullptr) { + return ERR_INVALID_VALUE; + } + int32_t st = Remote()->SendRequest(COMMAND_TEST_INT_TRANSACTION, data, reply, option); + if (st != ERR_NONE) { + return st; + } + + ErrCode ec = reply.ReadInt32(); + if (FAILED(ec)) { + return ec; + } + + result = reply.ReadInt32(); + return ERR_OK; +} + +ErrCode IdlTestServiceProxy::TestStringTransaction( + /* [in] */ const std::string& _data) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + return ERR_INVALID_VALUE; + } + + data.WriteString16(Str8ToStr16(_data)); + + if (Remote() == nullptr) { + return ERR_INVALID_VALUE; + } + int32_t st = Remote()->SendRequest(COMMAND_TEST_STRING_TRANSACTION, data, reply, option); + if (st != ERR_NONE) { + return st; + } + + ErrCode ec = reply.ReadInt32(); + if (FAILED(ec)) { + return ec; + } + + return ERR_OK; +} +} +``` + +#### 3.1.3 客户端调用IPC方法 + + 客户端调用connectAbility()以连接服务时,客户端的onAbilityConnectDone()回调会接收服务的onConnect()方法返回的IRemoteObject实例。由于客户端和服务在不同应用内,所以客户端应用的src/目录内必须包含.idl文件(SDK工具会自动生成Proxy代理类)的副本。当客户端onAbilityConnectDone()回调中收到IRemoteObject,调用RemoteAbilityStub.asInterface(IRemoteObject),以将返回的参数转换为IRemoteAbility类型,示例代码如下: + +``` +#ifndef OHOS_IDLTESTSERVICEPROXY_H +#define OHOS_IDLTESTSERVICEPROXY_H +#include +#include "iidl_test_service.h" + +namespace OHOS { +class IdlTestServiceProxy : public IRemoteProxy { +public: + explicit IdlTestServiceProxy( + /* [in] */ const sptr& remote) + : IRemoteProxy(remote) + {} + + virtual ~IdlTestServiceProxy() + {} + + ErrCode TestIntTransaction( + /* [in] */ int _data, + /* [out] */ int& result) override; + + ErrCode TestStringTransaction( + /* [in] */ const std::string& _data) override; + +private: + static constexpr int COMMAND_TEST_INT_TRANSACTION = MIN_TRANSACTION_ID + 0; + static constexpr int COMMAND_TEST_STRING_TRANSACTION = MIN_TRANSACTION_ID + 1; + + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS +#endif +``` + +如果要断开连接,请调用Ability.disconnectAbility()。 + + + +### 3.2 TS开发步骤 + +#### 3.2.1 创建.idl文件 + + 开发者可以使用TS编程语言构建.idl文件。.idl示例如下: + +``` + interface OHOS.IIdlTestService { + int TestIntTransaction([in] int data); + void TestStringTransaction([in] String data); + } +``` + +使用者通过执行命令 “./idl -c IIdlTestService.idl -gen-ts -d /data/ts/” (-d为输出目录)在执行环境的/data/ts/目录中生成接口文件、Stub文件、Proxy文件。生成的接口类文件名称和.idl文件名称保持一致,区别在于其使用.ts扩展名。例如,IIdlTestService.idl 生成的文件名是 i_idl_test_service.ts、idl_test_service_proxy.ts、idl_test_service_stub.ts。 + +#### 3.2.2 服务端公开接口 + + OpenHarmony IDL工具生成的Stub类是接口类的抽象实现,并且会声明.idl文件中的所有方法。 + +``` +import {testIntTransactionCallback} from "./i_idl_test_service"; +import {testStringTransactionCallback} from "./i_idl_test_service"; +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); + } + + onRemoteRequest(code: number, data, reply, option): boolean { + console.log("onRemoteRequest called, code = " + code); + switch(code) { + case IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION: { + let _data = data.readInt(); + this.testIntTransaction(_data, (errCode, returnValue) => { + reply.writeInt(errCode); + if (errCode == 0) { + reply.writeInt(returnValue); + } + }); + return true; + } + case IdlTestServiceStub.COMMAND_TEST_STRING_TRANSACTION: { + let _data = data.readString(); + this.testStringTransaction(_data, (errCode) => { + reply.writeInt(errCode); + }); + return true; + } + default: { + console.log("invalid request code" + code); + break; + } + } + return false; + } + + testIntTransaction(data: number, callback: testIntTransactionCallback): void{} + testStringTransaction(data: string, callback: testStringTransactionCallback): void{} + + static readonly COMMAND_TEST_INT_TRANSACTION = 1; + static readonly COMMAND_TEST_STRING_TRANSACTION = 2; +} +``` + +开发者需要继承.idl文件中定义的接口类并实现其中的方法。在本示例中,我们继承了IdlTestServiceStub接口类并实现了其中的testIntTransaction和testStringTransaction方法。具体的示例代码如下: + +``` +import {testIntTransactionCallback} from "./i_idl_test_service" +import {testStringTransactionCallback} from "./i_idl_test_service" +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); + } +} +``` + +在服务实现接口后,需要向客户端公开该接口,以便客户端进程绑定。如果开发者的服务要公开该接口,请扩展Ability并实现onConnect()从而返回IRemoteObject,以便客户端能与服务进程交互。服务端向客户端公开IRemoteAbility接口的代码示例如下: + +``` +export default { + onStart() { + console.info('ServiceAbility onStart'); + }, + onStop() { + console.info('ServiceAbility onStop'); + }, + onCommand(want, startId) { + console.info('ServiceAbility onCommand'); + }, + onConnect(want) { + 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) { + console.log("ServiceAbility error:" + err) + } + console.info('ServiceAbility onConnect end'); + return new IdlTestImp('connect'); + }, + onDisconnect(want) { + console.info('ServiceAbility onDisconnect'); + console.info('ServiceAbility want:' + JSON.stringify(want)); + } +}; +``` + +#### 3.2.3 客户端调用IPC方法 + +客户端调用connectAbility()以连接服务时,客户端的onAbilityConnectDone()回调会接收服务的onConnect()方法返回的IRemoteObject实例。由于客户端和服务在不同应用内,所以客户端应用的目录内必须包含.idl文件(SDK工具会自动生成Proxy代理类)的副本。当客户端onAbilityConnectDone()回调中收到IRemoteObject,使用IRemoteObject创建IdlTestServiceProxy类的实例对象testProxy,然后调用相关IPC方法。示例代码如下: + +``` +import IdlTestServiceProxy from './idl_test_service_proxy' +import featureAbility from '@ohos.ability.featureAbility'; + +function callbackTestIntTransaction(result: number, ret: number): void { + if (result == 0 && ret == 124) { + console.log("case 1 success "); + } +} + +function callbackTestStringTransaction(result: number): void { + if (result == 0) { + console.log("case 2 success "); + } +} + +var onAbilityConnectDone = { + onConnect:function (elementName, proxy) { + let testProxy = new IdlTestServiceProxy(proxy); + testProxy.testIntTransaction(123, callbackTestIntTransaction); + testProxy.testStringTransaction('hello', callbackTestStringTransaction); + }, + onDisconnect:function (elementName) { + console.log("onDisconnectService onDisconnect"); + }, + onFailed:function (code) { + console.log("onDisconnectService onFailed"); + } +}; + +function connectAbility: void { + let want = { + "bundleName":"com.example.myapplicationidl", + "abilityName": "com.example.myapplicationidl.ServiceAbility" + }; + let connectionId = -1; + connectionId = featureAbility.connectAbility(want, onAbilityConnectDone); +} + + +``` + +#### 3.2.4 IPC传递Sequenceable对象 + +开发者可以通过 IPC 接口,将某个类从一个进程发送至另一个进程。但是,必须确保 IPC 通道的另一端可使用该类的代码,并且该类必须支持marshalling和unmarshalling方法。OpenHarmony 需要通过该marshalling和unmarshalling方法将对象序列化和反序列化成各进程能识别的对象。 + +如需创建支持Sequenceable 类型数据,开发者必须执行以下操作: + +1. 实现marshalling方法,它会获取对象的当前状态并将其序列化后写入Parcel。 +2. 实现unmarshalling方法,它会从Parcel中反序列化出对象。 + +MySequenceable类的代码示例如下: + +``` +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; + } + marshalling(messageParcel) { + messageParcel.writeInt(this.num); + messageParcel.writeString(this.str); + return true; + } + unmarshalling(messageParcel) { + this.num = messageParcel.readInt(); + this.str = messageParcel.readString(); + return true; + } + private num; + private str; +} +``` + + + +## 4. C++与TS互通开发步骤 + +### 4.1 TS Proxy与C++ Stub开发步骤 + +#### 4.1.1 C++端提供服务对象 + +1. 如上所述C++开发步骤,开发者使用C++编程语言构建.idl文件,通过命令生成接口、Stub文件、Proxy文件。 + +2. 开发者创建服务对象,并继承C++ Stub文件中定义的接口类并实现其中的方法,例如: + + ``` + class IdlTestServiceImpl : public IdlTestServiceStub { + public: + IdlTestServiceImpl() = default; + virtual ~IdlTestServiceImpl() = default; + + ErrCode TestIntTransaction(int _data, int& result) override + { + result = 256; + return ERR_OK; + } + + ErrCode TestStringTransaction(const std::string& _data) override + { + return ERR_OK; + } + }; + ``` + +#### 4.1.2 C++端提供napi接口 + +C++需要通过napi的方式,把C++服务对象提供给TS端,例如:C++端提供一个GetNativeObject方法,方法里创建IdlTestServiceImpl实例,通过NAPI_ohos_rpc_CreateJsRemoteObject方法,创建出一个JS远程对象供TS应用使用,如下: + +``` +NativeValue* GetNativeObject(NativeEngine& engine, NativeCallbackInfo& info) +{ + sptr impl = new IdlTestServiceImpl(); + napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(reinterpret_cast(&engine), impl); + NativeValue* nativeRemoteObject = reinterpret_cast(napiRemoteObject); + return nativeRemoteObject; +} +``` + +#### 4.1.3 TS端提供Proxy对象 + +如上所述TS开发步骤,开发者使用TS编程语言构建.idl文件,通过命令生成接口、Stub文件、Proxy文件。Proxy文件例如: + +``` +idl_test_service_proxy.ts + +import {testIntTransactionCallback} from "./i_idl_test_service"; +import {testStringTransactionCallback} from "./i_idl_test_service"; +import IIdlTestService from "./i_idl_test_service"; +import rpc from "@ohos.rpc"; + +export default class IdlTestServiceProxy implements IIdlTestService { + constructor(proxy) { + this.proxy = proxy; + } + + testIntTransaction(data: number, callback: testIntTransactionCallback): void + { + let _option = new rpc.MessageOption(rpc.MessageOption.TF_SYNC); + let _data = new rpc.MessageParcel(); + let _reply = new rpc.MessageParcel(); + _data.writeInt(data); + this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_INT_TRANSACTION, _data, _reply, _option).then(function(result) { + if (result.errCode === 0) { + let _errCode = result.reply.readInt(); + if (_errCode != 0) { + let _returnValue = undefined; + callback(_errCode, _returnValue); + return; + } + let _returnValue = result.reply.readInt(); + callback(_errCode, _returnValue); + } else { + console.log("sendRequest failed, errCode: " + result.errCode); + } + }) + } + + testStringTransaction(data: string, callback: testStringTransactionCallback): void + { + let _option = new rpc.MessageOption(rpc.MessageOption.TF_SYNC); + let _data = new rpc.MessageParcel(); + let _reply = new rpc.MessageParcel(); + _data.writeString(data); + this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_STRING_TRANSACTION, _data, _reply, _option).then(function(result) { + if (result.errCode === 0) { + let _errCode = result.reply.readInt(); + callback(_errCode); + } else { + console.log("sendRequest failed, errCode: " + result.errCode); + } + }) + } + + static readonly COMMAND_TEST_INT_TRANSACTION = 1; + static readonly COMMAND_TEST_STRING_TRANSACTION = 2; + private proxy +} +``` + +#### 4.1.4 TS与C++实现互通 + +1. TS应用调用napi接口获取C++服务的远程对象 +2. 构建TS Proxy对象,并把C++服务的远程对象传递给它 +3. 此时开发者通过TS Proxy对象调用.idl声明的方法,实现TS Proxy与C++ Stub的互通,示例如下: + +``` +import IdlTestServiceProxy from './idl_test_service_proxy' +import nativeMgr from 'nativeManager'; + +function testIntTransactionCallback(errCode: number, returnValue: number) +{ + console.log("errCode: " + errCode + " returnValue: " + returnValue); +} + +function testStringTransactionCallback(errCode: number) +{ + console.log("errCode: " + errCode); +} + +function jsProxyTriggerCppStub() +{ + let nativeObj = nativeMgr.GetNativeObject(); + let tsProxy = new IdlTestServiceProxy(nativeObj); + // invoke testIntTransaction + tsProxy.testIntTransaction(10, testIntTransactionCallback); + + // invoke testStringTransaction + tsProxy.testStringTransaction("test", testIntTransactionCallback); +} +``` + diff --git a/zh-cn/application-dev/IDL/figures/IDL-interface-description.png b/zh-cn/application-dev/IDL/figures/IDL-interface-description.png new file mode 100644 index 0000000000000000000000000000000000000000..2113efce4828c9fc60a855b64fa9065b7f6be484 GIT binary patch literal 31975 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 literal 0 HcmV?d00001 -- GitLab