OpenHarmony-7.IDL工具

server/2025/1/19 12:47:42/
  • IDL 工具

1.openharmony IDL工具

  在OpenHarmony中,当应用/系统服务的客户端和服务端进行IPC(Inter-Process Communication)跨线程通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony IDL(Interface Definition Language)则是一种定义此类接口的工具。OpenHarmony IDL先把需要传递的对象分解成操作系统能够理解的基本类型,并根据开发者的需要封装跨边界的对象。
在这里插入图片描述  OpenHarmony IDL接口描述语言主要用于:

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

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

  使用OpenHarmony IDL接口描述语言声明接口具有以下优点:

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

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

1.1.接口说明

Native侧IPC接口
在这里插入图片描述

1.2.开发步骤:参考IDL开发指南

1.2.1.获取IDL工具

  在linux系统,下载OpenHarmony的两个仓:ability_idl_tool代码仓、third_party_bounds_checking_function代码仓。进入ability_idl_tool代码仓,在Makefile所在目录执行make命令(注意修改MakefileLinux中关于bounds_checking_function的相对位置)。make执行完成后,在当前目录下会生成idl-gen可执行文件,可用于idl文件本地调试。

  代码下载:

  • https://gitee.com/openharmony/ability_idl_tool.git
  • https://gitee.com/openharmony/third_party_bounds_checking_function.git

  执行编译:

  • 将ability_idl_tool(master分支)和third_party_bounds_checking_function下载到同级目录,然后创建third_party目录,并把third_party_bounds_checking_function改为bounds_checking_function拷贝到third_party目录。
  • 修改MakefileLinux:
 14 #BOUNDS_CHECK_DIR := $(abspath ../../../third_party/bounds_checking_function)15 BOUNDS_CHECK_DIR := $(abspath ../third_party/bounds_checking_function)44 #BOUNDS_CHECK_SOURCE_DIR := $(abspath ../../../third_party/bounds_checking_function/src)45 BOUNDS_CHECK_SOURCE_DIR := $(abspath ../third_party/bounds_checking_function/src)
  • 执行make,生成idl-gen。

1.2.2.创建.idl文件

  创建目录IIdlTestService,构建名为IIdlTestService.idl的文件,内容如下:

 16 interface OHOS.IIdlTestService {17     void TestIntTransaction([in] int val);18     void TestStringTransaction([in] String val);19 }

  在idl的可执行文件所在文件夹下执行命令:

ability_idl_tool$ ./idl-gen -gen-cpp -d IIdlTestService -c IIdlTestService/IIdlTestService.idl //生成cpp文件
ability_idl_tool$ ./idl-gen -gen-ts -d IIdlTestService -c IIdlTestService/IIdlTestService.idl //生成ts文件

  -d后的dir为目标输出目录,以输出文件夹名为IIdlTestService为例,在idl可执行文件所在目录下执行./idl-gen -gen-cpp -d IIdlTestService -c IIdlTestService/IIdlTestService.idl,将会在执行环境的IIdlTestService目录中生成接口文件、Stub文件、Proxy文件。

注意:生成的接口类文件名称和.idl文件名称保持一致,否则会生成代码时会出现错误。

  以IIdlTestService为例,其目录结构应类似于:

ability_idl_tool/IIdlTestService$ ls
idl_test_service_proxy.cpp  idl_test_service_stub.cpp  iidl_test_service.h
idl_test_service_proxy.h    idl_test_service_stub.h    IIdlTestService.idl

2.案例介绍

  • 定义IPC接口ITestAbility

  SA接口继承IPC基类接口IRemoteBroker,接口里定义描述符、业务函数和消息码,其中业务函数在Proxy端和Stub端都需要实现。

#include "iremote_broker.h"//定义消息码
const int TRANS_ID_PING_ABILITY = 5;const std::string DESCRIPTOR = "test.ITestAbility";class ITestAbility : public IRemoteBroker {
public:// DECLARE_INTERFACE_DESCRIPTOR是必需的,入参需使用std::u16string;DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR));virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数
};
  • 定义和实现服务端TestAbilityStub
    该类是和IPC框架相关的实现,需要继承 IRemoteStub。Stub端作为接收请求的一端,需重写OnRemoteRequest方法用于接收客户端调用。
#include "iability_test.h"
#include "iremote_stub.h"class TestAbilityStub : public IRemoteStub<ITestAbility> {
public:virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;int TestPingAbility(const std::u16string &dummy) override;};int TestAbilityStub::OnRemoteRequest(uint32_t code,MessageParcel &data, MessageParcel &reply, MessageOption &option)
{switch (code) {case TRANS_ID_PING_ABILITY: {std::u16string dummy = data.ReadString16();int result = TestPingAbility(dummy);reply.WriteInt32(result);return 0;}default:return IPCObjectStub::OnRemoteRequest(code, data, reply, option);}
}
  • 定义服务端业务函数具体实现类TestAbility
#include "iability_server_test.h"class TestAbility : public TestAbilityStub {
public:int TestPingAbility(const std::u16string &dummy);
}int TestAbility::TestPingAbility(const std::u16string &dummy) {return 0;
}
  • 定义和实现客户端 TestAbilityProxy
    该类是Proxy端实现,继承IRemoteProxy,调用SendRequest接口向Stub端发送请求,对外暴露服务端提供的能力。
#include "iability_test.h"
#include "iremote_proxy.h"
#include "iremote_object.h"class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
public:explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);int TestPingAbility(const std::u16string &dummy) override;
private:static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便后续使用iface_cast宏
}TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl): IRemoteProxy<ITestAbility>(impl)
{
}int TestAbilityProxy::TestPingAbility(const std::u16string &dummy){MessageOption option;MessageParcel dataParcel, replyParcel;dataParcel.WriteString16(dummy);int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;return result;
}
  • SA注册与启动
    SA需要将自己的TestAbilityStub实例通过AddSystemAbility接口注册到SystemAbilityManager,设备内与分布式的注册参数不同。
// 注册到本设备内
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
samgr->AddSystemAbility(saId, new TestAbility());// 在组网场景下,会被同步到其他设备上
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ISystemAbilityManager::SAExtraProp saExtra;
saExtra.isDistributed = true; // 设置为分布式SA
int result = samgr->AddSystemAbility(saId, new TestAbility(), saExtra);
  • SA获取与调用
    通过SystemAbilityManager的GetSystemAbility方法可获取到对应SA的代理IRemoteObject,然后构造TestAbilityProxy即可。
// 获取本设备内注册的SA的proxy
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId);
sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // 使用iface_cast宏转换成具体类型// 获取其他设备注册的SA的proxy
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();// networkId是组网场景下对应设备的标识符,可以通过GetLocalNodeDeviceInfo获取
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId, networkId);
sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // 直接构造具体Proxy

2.调用原理

  在IPC模式下,当系统服务调用HDI接口时,通过proxy库将函数调用转换为IPC请求,将接口调用的参数进行序列化;IPC请求通过IPC框架发送到服务端,请求将被stub库先处理,然后对接口调用的参数进行反序列化,再转换成对服务实现的函数调用,从而实现接口调用过程。

  HDI调用过程:
在这里插入图片描述

refer to
-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
https://gitee.com/openharmony/docs/blob/bf3b0969af6c0a9830b6761edeb96e7f37c7d449/zh-cn/application-dev/ipc/ipc-rpc-development-guideline.md


http://www.ppmy.cn/server/159632.html

相关文章

开发规范

开发规范 企业项目开发有2种开发模式&#xff1a;前后台混合开发和前后台分离开发。 前后台混合开发 顾名思义就是前台后台代码混在一起开发&#xff0c;如下图所示&#xff1a; 这种开发模式有如下缺点&#xff1a; 沟通成本高&#xff1a;后台人员发现前端有问题&#xf…

机器学习 - 如何理解几何学中的超平面 ?

线性回归公式 ywTxb 是数据建模中的基础&#xff1a; 数学上&#xff0c;它是一个线性函数。几何上&#xff0c;它是一个超平面。 那么如何理解超平面这个概念呢&#xff1f; 超平面&#xff08;hyperplane&#xff09;是几何学中的一个基本概念&#xff0c;尤其在高维空间和…

windows蓝牙驱动开发-BLE音频(三)

序列 音频驱动程序初始化 当 IHV ACX 流式处理驱动程序加载并确定它支持蓝牙 LE 音频流式处理时&#xff0c;它应通过以下方法来显示对该技术的支持&#xff1a;创建 ACXFACTORYCIRCUIT 对象&#xff0c;并使用音频终结点模板绑定 ID 中定义的 ID 向 ACX 注册蓝牙模板绑定。 …

【AIGC-ChatGPT进阶提示词指令】心灵修复师:一个基于情感共鸣的智慧对话系统设计

引言 在当今快节奏的生活中&#xff0c;心理健康问题日益凸显。如何借助人工智能技术&#xff0c;构建一个既富有温度又专业可靠的心理支持系统&#xff0c;成为了一个值得深入探讨的课题。本文将详细介绍一个名为"心灵修复师"的对话系统设计&#xff0c;这个系统通…

人脸识别【python-基于OpenCV】

1. 导入并显示图片 #导入模块 import cv2 as cv#读取图片 imgcv.imread(img/wx(1).jpg) #路径名为全英文&#xff0c;出现中文 图片加载失败,"D:\picture\wx.jpg" #显示图片 &#xff08;显示标题&#xff0c;显示图片对象&#xff09; cv.imshow(read_picture,im…

Debian终端高亮(显示不同颜色)

起因 Debian终端与CentOS不一样&#xff0c;CentOS终端默认自带高亮显示&#xff0c;不同文件类型的文件显示颜色不一样&#xff0c;而Debian默认都显示为一样的颜色。 解决方法 为了debian终端显示有颜色有如下方法&#xff1a; 方法一&#xff1a;单次有效 ls --colorau…

【Leetcode 热题 100】295. 数据流的中位数

问题背景 中位数 是有序整数列表中的中间值。如果列表的大小是偶数&#xff0c;则没有中间值&#xff0c;中位数是两个中间值的平均值。 例如 a r r [ 2 , 3 , 4 ] arr [2,3,4] arr[2,3,4] 的中位数是 3 3 3。例如 a r r [ 2 , 3 ] arr [2,3] arr[2,3] 的中位数是 ( …

网络编程 | UDP广播通信

1、什么是广播 在上一篇博客文章中已经对UDP进行了详细的说明介绍及如何编程实现。本文将接着上一文的内容&#xff0c;在其基础上&#xff0c;对UDP的知识体系进一步深入的讲解。 网络编程 | UDP套接字通信及编程实现经验教程-CSDN博客 例子&#xff1a;在一些中小学的操场中&…