• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..17-Mar-2025-

ast/H17-Mar-2025-2,4451,448

codegen/H17-Mar-2025-4,1333,537

figures/H17-Mar-2025-

idl_tool_2/H17-Mar-2025-36,95527,759

metadata/H17-Mar-2025-1,6741,170

parser/H17-Mar-2025-1,5151,245

scripts/H17-Mar-2025-8357

test/H17-Mar-2025-549,774448,154

util/H17-Mar-2025-2,3441,723

BUILD.gnH A D17-Mar-20252.1 KiB8674

LICENSEH A D17-Mar-202510.1 KiB177150

MakefileH A D17-Mar-20251.1 KiB3517

MakefileLinuxH A D17-Mar-20253.4 KiB8768

OAT.xmlH A D17-Mar-20254.3 KiB7420

README.mdH A D17-Mar-202513.4 KiB392304

bundle.jsonH A D17-Mar-20251.4 KiB4948

idl_config.gniH A D17-Mar-20258.2 KiB274261

idl_tool.gniH A D17-Mar-2025637 1513

main.cppH A D17-Mar-20253.8 KiB139105

README.md

1# IDL工具
2
3## 简介
4
5在OpenHarmony中,当应用/系统服务的客户端和服务端进行IPC(Inter-Process Communication)跨线程通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony IDL(Interface Definition Language)则是一种定义此类接口的工具。OpenHarmony IDL先把需要传递的对象分解成操作系统能够理解的基本类型,并根据开发者的需要封装跨边界的对象。
6
7  **图1** IDL接口描述
8  ![IDL-interface-description](./figures/IDL-interface-description.png)
9
10OpenHarmony  IDL接口描述语言主要用于:
11
12- 声明系统服务对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。
13
14- 声明Ability对外提供的服务接口,根据接口声明在编译时生成跨进程调用(IPC)或跨设备调用(RPC)的代理(Proxy)和桩(Stub)的C/C++代码或JS/TS代码。
15
16**图2** IPC/RPC通信模型
17
18![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png)
19
20使用OpenHarmony IDL接口描述语言声明接口具有以下优点:
21
22- OpenHarmony IDL中是以接口的形式定义服务,可以专注于定义而隐藏实现细节。
23
24- OpenHarmony IDL中定义的接口可以支持跨进程调用或跨设备调用。根据OpenHarmony IDL中的定义生成的信息或代码可以简化跨进程或跨设备调用接口的实现。
25
26**部件内子模块职责**
27
28| 子模块名称       | 职责                                                         |
29| ---------------- | ------------------------------------------------------------|
30| 接口文件解析模块         | 解析校验接口定义文件。                                    |
31| stub/proxy自动生成模块   | 根据IPC/RPC规格自动生成Stub服务端和Proxy客户端代码。         |
32
33## 目录
34
35```
36foundation/ability/idl_tool
37├── ast                         # idl语法解析定义代码
38├── codegen                     # 模板生成模块代码
39├── hash                        # hash生成模块代码
40├── lexer                       # 词法解析模块代码
41├── metadata                    # matedata自定义数据解析模块代码
42├── parser                      # 语法解析模块代码
43├── preprocessor                # 预处理模块代码
44├── test                        # 测试目录
45└── util                        # 公共方法代码
46```
47
48## 开发步骤
49idl工具的获取和TS开发步骤可参考[开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/IDL/idl-guidelines.md#31-c%E5%BC%80%E5%8F%91%E6%AD%A5%E9%AA%A4)50
51### C++开发步骤
52
53#### 创建.idl文件
54
55开发者可以使用C++编程语言构建.idl文件。
56
57例如,此处构建一个名为IIdlTestService.idl的文件,文件内具体内容如下:
58
59```cpp
60  interface OHOS.IIdlTestService {
61      int TestIntTransaction([in] int data);
62      void TestStringTransaction([in] String data);
63  }
64```
65
66在idl的可执行文件所在文件夹下执行命令 `idl -gen-cpp -d dir -c dir/IIdlTestService.idl`。
67
68-d后的dir为目标输出目录,以输出文件夹名为IIdlTestServiceCpp为例,在idl可执行文件所在目录下执行`idl -gen-cpp -d IIdlTestServiceCpp -c IIdlTestServiceCpp/IIdlTestService.idl`,将会在执行环境的dir目录(即IIdlTestServiceCpp目录)中生成接口文件、Stub文件、Proxy文件。
69
70 > **注意**:生成的接口类文件名称和.idl文件名称保持一致,否则会生成代码时会出现错误。
71
72以名为`IIdlTestService.idl`的.idl文件、目标输出文件夹为IIdlTestServiceCpp为例,其目录结构应类似于:
73
74```
75├── IIdlTestServiceCpp  # idl代码输出文件夹
76│   ├── iidl_test_service.h  # 生成文件
77│   ├── idl_test_service_proxy.h  # 生成文件
78│   ├── idl_test_service_stub.h  # 生成文件
79│   ├── idl_test_service_proxy.cpp  # 生成文件
80│   ├── idl_test_service_stub.cpp  # 生成文件
81│   └── IIdlTestService.idl  # 构造的.idl文件
82└── idl.exe  # idl的可执行文件
83```
84
85#### 服务端公开接口
86
87OpenHarmony IDL工具生成的Stub类是接口类的抽象实现,并且会声明.idl文件中的所有方法。
88
89```cpp
90#ifndef OHOS_IDLTESTSERVICESTUB_H
91#define OHOS_IDLTESTSERVICESTUB_H
92#include <iremote_stub.h>
93#include "iidl_test_service.h"
94
95namespace OHOS {
96class IdlTestServiceStub : public IRemoteStub<IIdlTestService> {
97public:
98    int OnRemoteRequest(
99        /* [in] */ uint32_t code,
100        /* [in] */ MessageParcel& data,
101        /* [out] */ MessageParcel& reply,
102        /* [in] */ MessageOption& option) override;
103
104private:
105    static constexpr int COMMAND_TEST_INT_TRANSACTION = MIN_TRANSACTION_ID + 0;
106    static constexpr int COMMAND_TEST_STRING_TRANSACTION = MIN_TRANSACTION_ID + 1;
107};
108} // namespace OHOS
109#endif // OHOS_IDLTESTSERVICESTUB_H
110```
111
112开发者需要继承.idl文件中定义的接口类并实现其中的方法,同时在服务侧初始化时需要将定义的服务注册至SAMGR中,在本示例中,TestService类继承了IdlTestServiceStub接口类并实现了其中的TestIntTransaction和TestStringTransaction方法。具体的示例代码如下:
113
114```cpp
115#ifndef OHOS_IPC_TEST_SERVICE_H
116#define OHOS_IPC_TEST_SERVICE_H
117
118#include "hilog/log.h"
119#include "log_tags.h"
120#include "idl_test_service_stub.h"
121
122namespace OHOS {
123class TestService : public IdlTestServiceStub {
124public:
125    TestService();
126    ~TestService();
127    static int Instantiate();
128    ErrCode TestIntTransaction(int data, int &rep) override;
129    ErrCode TestStringTransaction(const std::string& data) override;
130private:
131    static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestService" };
132};
133} // namespace OHOS
134#endif // OHOS_IPC_TEST_SERVICE_H
135```
136
137注册服务的示例代码如下:
138
139```cpp
140#include "test_service.h"
141
142#include <string_ex.h>
143
144#include "if_system_ability_manager.h"
145#include "ipc_debug.h"
146#include "ipc_skeleton.h"
147#include "iservice_registry.h"
148#include "system_ability_definition.h"
149
150namespace OHOS {
151using namespace OHOS::HiviewDFX;
152
153int TestService::Instantiate()
154{
155    ZLOGI(LABEL, "%{public}s call in", __func__);
156    auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
157    if (saMgr == nullptr) {
158        ZLOGE(LABEL, "%{public}s:fail to get Registry", __func__);
159        return -ENODEV;
160    }
161
162    sptr<IRemoteObject> newInstance = new TestService();
163    int result = saMgr->AddSystemAbility(IPC_TEST_SERVICE, newInstance);
164    ZLOGI(LABEL, "%{public}s: IPC_TEST_SERVICE result = %{public}d", __func__, result);
165    return result;
166}
167
168TestService::TestService()
169{
170}
171
172TestService::~TestService()
173{
174}
175
176ErrCode TestService::TestIntTransaction(int data, int &rep)
177{
178    ZLOGE(LABEL, " TestService:read from client data = %{public}d", data);
179    rep = data + data;
180    return ERR_NONE;
181}
182
183ErrCode TestService::TestStringTransaction(const std::string &data)
184{
185    ZLOGE(LABEL, "TestService:read string from client data = %{public}s", data.c_str());
186    return data.size();
187}
188} // namespace OHOS
189```
190
191#### 客户端调用IPC方法
192
193C++客户端通常通过SAMGR获取系统中定义的服务代理,随后即可正常调用proxy提供的接口。示例代码如下:
194
195```cpp
196#include "test_client.h"
197
198#include "if_system_ability_manager.h"
199#include "ipc_debug.h"
200#include "ipc_skeleton.h"
201#include "iservice_registry.h"
202#include "system_ability_definition.h"
203
204namespace OHOS {
205int TestClient::ConnectService()
206{
207    auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
208    if (saMgr == nullptr) {
209        ZLOGE(LABEL, "get registry fail");
210        return -1;
211    }
212
213    sptr<IRemoteObject> object = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
214    if (object != nullptr) {
215        ZLOGE(LABEL, "Got test Service object");
216        testService_ = (new (std::nothrow) IdlTestServiceProxy(object));
217    }
218
219    if (testService_ == nullptr) {
220        ZLOGE(LABEL, "Could not find Test Service!");
221        return -1;
222    }
223
224    return 0;
225}
226
227void TestClient::StartIntTransaction()
228{
229    if (testService_ != nullptr) {
230        ZLOGE(LABEL, "StartIntTransaction");
231        [[maybe_unused]] int result = 0;
232        testService_->TestIntTransaction(1234, result); // 1234 : test number
233        ZLOGE(LABEL, "Rec result from server %{public}d.", result);
234    }
235}
236
237void TestClient::StartStringTransaction()
238{
239    if (testService_ != nullptr) {
240        ZLOGI(LABEL, "StartIntTransaction");
241        testService_->TestStringTransaction("IDL Test");
242    }
243}
244} // namespace OHOS
245```
246
247## C++与TS互通开发步骤
248
249### TS Proxy与C++ Stub开发步骤
250
251#### C++端提供服务对象
252
2531. 如上所述C++开发步骤,开发者使用C++编程语言构建.idl文件,通过命令生成接口、Stub文件、Proxy文件。
254
2552. 开发者创建服务对象,并继承C++ Stub文件中定义的接口类并实现其中的方法,例如:
256
257   ```cpp
258   class IdlTestServiceImpl : public IdlTestServiceStub {
259   public:
260       IdlTestServiceImpl() = default;
261       virtual ~IdlTestServiceImpl() = default;
262
263       ErrCode TestIntTransaction(int _data, int& result) override
264       {
265            result = 256;
266            return ERR_OK;
267       }
268
269       ErrCode TestStringTransaction(const std::string& _data) override
270       {
271            return ERR_OK;
272       }
273   };
274   ```
275
276#### C++端提供napi接口
277
278C++需要通过napi的方式,把C++服务对象提供给TS端,例如:C++端提供一个GetNativeObject方法,方法里创建IdlTestServiceImpl实例,通过NAPI_ohos_rpc_CreateJsRemoteObject方法,创建出一个JS远程对象供TS应用使用,如下:
279
280```cpp
281napi_value GetNativeObject(napi_env engine, napi_callback_info info)
282{
283    sptr<IdlTestServiceImpl> impl = new IdlTestServiceImpl();
284    napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(engine, impl);
285    return nativeRemoteObject;
286}
287```
288
289#### TS端提供Proxy对象
290
291如上所述TS开发步骤,开发者使用TS编程语言构建.idl文件,通过命令生成接口、Stub文件、Proxy文件。Proxy文件例如:
292
293```ts
294import {testIntTransactionCallback} from "./i_idl_test_service";
295import {testStringTransactionCallback} from "./i_idl_test_service";
296import IIdlTestService from "./i_idl_test_service";
297import rpc from "@ohos.rpc";
298
299export default class IdlTestServiceProxy implements IIdlTestService {
300    constructor(proxy) {
301        this.proxy = proxy;
302    }
303
304    testIntTransaction(data: number, callback: testIntTransactionCallback): void
305    {
306        let _option = new rpc.MessageOption();
307        let _data = new rpc.MessageParcel();
308        let _reply = new rpc.MessageParcel();
309        _data.writeInt(data);
310        this.proxy.sendMessageRequest(IdlTestServiceProxy.COMMAND_TEST_INT_TRANSACTION, _data, _reply, _option).then(function(result) {
311            if (result.errCode == 0) {
312                let _errCode = result.reply.readInt();
313                if (_errCode != 0) {
314                    let _returnValue = undefined;
315                    callback(_errCode, _returnValue);
316                    return;
317                }
318                let _returnValue = result.reply.readInt();
319                callback(_errCode, _returnValue);
320            } else {
321                console.log('sendMessageRequest failed, errCode: ' + result.errCode);
322            }
323        })
324    }
325
326    testStringTransaction(data: string, callback: testStringTransactionCallback): void
327    {
328        let _option = new rpc.MessageOption();
329        let _data = new rpc.MessageParcel();
330        let _reply = new rpc.MessageParcel();
331        _data.writeString(data);
332        this.proxy.sendMessageRequest(IdlTestServiceProxy.COMMAND_TEST_STRING_TRANSACTION, _data, _reply, _option).then(function(result) {
333            if (result.errCode == 0) {
334                let _errCode = result.reply.readInt();
335                callback(_errCode);
336            } else {
337                console.log('sendMessageRequest failed, errCode: ' + result.errCode);
338            }
339        })
340    }
341
342    static readonly COMMAND_TEST_INT_TRANSACTION = 1;
343    static readonly COMMAND_TEST_STRING_TRANSACTION = 2;
344    private proxy
345}
346```
347
348#### TS与C++实现互通
349
3501. TS应用调用napi接口获取C++服务的远程对象
3512. 构建TS Proxy对象,并把C++服务的远程对象传递给它
3523. 此时开发者通过TS Proxy对象调用.idl声明的方法,实现TS Proxy与C++ Stub的互通,示例如下:
353
354```ts
355import IdlTestServiceProxy from './idl_test_service_proxy'
356import nativeMgr from 'nativeManager';
357
358function testIntTransactionCallback(errCode: number, returnValue: number)
359{
360    console.log('errCode: ' + errCode + '  returnValue: ' + returnValue);
361}
362
363function testStringTransactionCallback(errCode: number)
364{
365    console.log('errCode: ' + errCode);
366}
367
368function jsProxyTriggerCppStub()
369{
370    let nativeObj = nativeMgr.GetNativeObject();
371    let tsProxy = new IdlTestServiceProxy(nativeObj);
372    // invoke testIntTransaction
373    tsProxy.testIntTransaction(10, testIntTransactionCallback);
374
375    // invoke testStringTransaction
376    tsProxy.testStringTransaction('test', testIntTransactionCallback);
377}
378```
379
380## 相关仓
381元能力子系统
382
383[ability_base](https://gitee.com/openharmony/ability_ability_base)
384
385[ability_runtime](https://gitee.com/openharmony/ability_ability_runtime)
386
387[dmsfwk](https://gitee.com/openharmony/ability_dmsfwk)
388
389[form_fwk](https://gitee.com/openharmony/ability_form_fwk)
390
391[**idl_tool**](https://gitee.com/openharmony/ability_idl_tool)
392