0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于OpenHarmony标准系统的C++公共基础类库案例:Semaphore

福州市凌睿智捷电子有限公司 2025-02-10 18:08 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1、程序简介

该程序是基于OpenHarmony标准系统的C++公共基础类库的线程处理:Sempahore。

本案例完成如下工作:

(1)无名信号量使用方法

定义1个无名信号量,1个供无名信号量管理的公共资源变量;

创建5个线程,每个线程做5次for循环,for循环的内容是获取无名信号量,并修改公共资源变量;

(2)有名信号量使用方法

定义1个有名信号量,1个供有名信号量管理的公共资源变量;

创建1个线程A,通过Open获取信号量,做5次for循环,for循环的内容是通过Wait获取有名信号量,如果获取成功则修改公共资源变量(即累加1),最后释放信号量;

创建1个线程B,通过Open获取信号量,做5次for循环,for循环的内容是通过TryWait获取有名信号量,如果获取成功则修改公共资源变量(即累加10),最后释放信号量;

创建1个线程C,通过Open获取信号量,做5次for循环,for循环的内容是通过TimedWait获取有名信号量,如果获取成功则修改公共资源变量(即累加100),最后释放信号量;

2、基础知识

C++公共基础类库为标准系统提供了一些常用的C++开发工具类,包括:

文件、路径、字符串相关操作的能力增强接口

读写锁、信号量、定时器、线程增强及线程池等接口

安全数据容器、数据序列化等接口

各子系统的错误码相关定义

2.1、添加C++公共基础类库依赖

修改需调用模块的BUILD.gn,在external_deps或deps中添加如下:

ohos_shared_library("xxxxx") { ... external_deps = [ ... # 动态库依赖(可选) "c_utils:utils", # 静态库依赖(可选) "c_utils:utilsbase", # Rust动态库依赖(可选) "c_utils:utils_rust", ] ...}

一般而言,我们只需要填写"c_utils:utils"即可。

2.2、Semaphore头文件

C++公共基础类库的Semaphore头文件在://commonlibrary/c_utils/base/include/semaphore_ex.h

可在源代码中添加如下:

#include

OpenHarmony信号量根据种类可以分为有名信号量和无名信号量,所以命令空间如下:

(1)无名信号量命名空间

OHOS::Semaphore

(2)有名信号量命名空间

OHOS::NamedSemaphore

2.3、OHOS::Samaphore接口说明

Semaphore为无名信号量。

2.3.1、Samaphore

构造函数, 构造一个Samaphore对象。

Semaphore(int value = 1);

参数说明:

参数名称类型参数说明
valueint信号量当前资源数量

2.3.2、~Semaphore

析构函数。

~Semaphore();

2.3.3、Wait

等待/获取信号量(即信号量 -1)。

void Wait();

2.3.4、Post

释放信号量(即信号量 +1)。

void Post();

2.4、OHOS::NamedSemaphore接口说明

NamedSemaphore为有名信号量。

2.4.1、NamedSemaphore

构造函数, 构造NamedSemaphore对象。

NamedSemaphore(size_t size)NamedSemaphore(const std::string& name, size_t size)

参数说明:

参数名称类型参数说明
namestd::string信号量名称
sizesize_t信号量有效资源数量

2.4.2、~NamedSemaphore

析构函数。

~NamedSemaphore();

2.4.3、Create

创建并初始化有名信号量。

bool Create();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.4、Unlink

将有名信号量文件从系统中删除。

bool Unlink();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.5、Open

打开一个已经创建的有名信号量文件。

bool Open();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.6、Close

关闭有名信号量。

bool Close();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.7、Wait

等待/获取信号量(信号量 -1)。

bool Wait();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.8、TryWait

等待/获取信号量(信号量 -1)的接口;非阻塞版。

bool TryWait();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.9、TimedWait

等待/获取信号量(信号量 -1);指定阻塞时间版。

bool TimedWait(const struct timespec& ts);

参数说明:

参数名称类型参数说明
tsstruct timespec绝对时间。注意:ts是utc时间,不是相对时间。

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.10、Post

释放信号量(信号量 +1)。

bool Post();

返回值说明:

类型返回值说明
booltrue表示成功,false表示失败

2.4.10、GetValue

获取信号的值。

int GetValue() const;

返回值说明:

类型返回值说明
int返回当前信号量的值

3、程序解析

3.1、创建编译引导

在//vendor/lockzhiner/rk3568/samples/BUILD.gn文件添加一行编译引导语句。

import("//build/ohos.gni")
group("samples") { deps = [ "a24_utils_semaphore:utils_semaphore", # 添加该行 ]}

"a24_utils_semaphore:utils_semaphore",该行语句表示引入参与编译。

3.2、创建编译项目

创建a24_utils_semaphore目录,并添加如下文件:

a24_utils_semaphore├── utils_name_semaphore.cpp # 有名信号量案例├── utils_noname_semaphore.cpp # 无名信号量案例├── BUILD.gn # GN文件

3.3、创建BUILD.gn

编辑BUILD.gn文件。

添加2个可执行程序,分别是:

utils_noname_semaphore:无名信号量使用案例

utils_name_semaphore:有名信号量使用案例

import("//build/ohos.gni")
ohos_executable("utils_noname_semaphore") { sources = [ "utils_noname_semaphore.cpp" ] include_dirs = [ "//commonlibrary/c_utils/base/include", "//commonlibrary/c_utils/base:utils", "//third_party/googletest:gtest_main", "//third_party/googletest/googletest/include", ] external_deps = [ "c_utils:utils" ] part_name = "product_rk3568" install_enable = true}
ohos_executable("utils_name_semaphore") { sources = [ "utils_name_semaphore.cpp" ] include_dirs = [ "//commonlibrary/c_utils/base/include", "//commonlibrary/c_utils/base:utils", "//third_party/googletest:gtest_main", "//third_party/googletest/googletest/include", ] external_deps = [ "c_utils:utils" ] part_name = "product_rk3568" install_enable = true}
group("utils_semaphore") { deps = [ ":utils_noname_semaphore", ":utils_name_semaphore", ]}

注意:

(1)BUILD.gn中所有的TAB键必须转化为空格,否则会报错。如果自己不知道如何规范化,可以:

# 安装gn工具sudo apt-get install ninja-buildsudo apt install generate-ninja# 规范化BUILD.gngn format BUILD.gn

3.4、无名信号量使用案例

3.4.1、添加信号量头文件

#include

3.4.2、创建无名信号量以及公共资源变量

static int m_count = 0; // 公共资源变量static OHOS::Semaphore m_sem(1); // 无名信号量

3.4.3、创建线程池

OHOS::ThreadPoolthreads("noname_semaphore_threads");

3.4.4、设置线程池

OHOS::ThreadPool threads("noname_semaphore_threads");

3.4.5、启动线程

for (int i = 0; i < threads_start; i++) { string str_name = "thread_" + to_string(i); auto task = std::bind(func, str_name); threads.AddTask(task); sleep(1);}

3.4.6、编写子线程代码

循环5次,每次循环调用信号量Wait()等待获取信号量。如果获取信号量后,将公共资源变量累加,调用信号量Post()释放信号量。

void func(const string &name){ for (int i = 0; i < 5; i++) { cout << name << ": Sema Wait..." << endl; m_sem.Wait(); cout << name << ": Sema Wait Successful" << endl; m_count += 1; m_sem.Post(); cout << name << ": Sema Post" << endl; sleep(1); }}

3.5、有名信号量使用案例

3.5.1、添加信号量头文件

#include

3.5.2、创建有名信号量

首先定义有名信号量,然后通过Create()创建全局有名信号量。

int main(int argc, char **argv){ OHOS::NamedSemaphore sem(STRING_NAME_SEMAPHORE, 1); ...... if (!sem.Create()) { cout << "NamedSemaphore.Create() failed\n"; return -1; } ......}

3.5.3、创建线程池

通过OHOS::ThreadPool定义线程池,调用SetMaxTaskNum()设置线程池最大线程数,并调用Start()设置当前启动多少个线程。

int main(int argc, char **argv){ OHOS::ThreadPool threads("name_semaphore_threads"); int threads_start = 3; ...... threads.SetMaxTaskNum(128); threads.Start(threads_start); ......}

3.5.4、启动子线程A、B和C

int main(int argc, char **argv){ ...... // 启动线程A str_name = "thread_a"; auto task_a = std::bind(funcA, str_name); threads.AddTask(task_a); // 启动线程B str_name = "thread_b"; auto task_b = std::bind(funcB, str_name); threads.AddTask(task_b);
// 启动线程A str_name = "thread_c"; auto task_c = std::bind(funcC, str_name); threads.AddTask(task_c); threads.Stop(); cout << "threads stop" << endl; return 0;}

3.5.5、编写子线程A

首先定义有名信号量,信号量数目可以随意设置。

其次,通过Open()打开有名信号量,可以与main()的有名信号量共享同一个信号量。

最后,通过Wait()和Post()来获取释放信号量。

static void funcA(const string &name){ OHOS::NamedSemaphore sem(STRING_NAME_SEMAPHORE, 1);
cout << get_curtime() << ", " << name << ": start\n";
// 打开一个已经创建的有名信号量文件 if (!sem.Open()) { cout << get_curtime() << ", " << name << ": sema open failed" << endl; return; } for (int i = 0; i < 5; i++) { cout << get_curtime() << ", " << name << ": sema wait..." << endl; sem.Wait(); cout << get_curtime() << ", " << name << ": sema wait success" << endl; m_count += 1; usleep(1000 * 1000 * 1); cout << get_curtime() << ", " << name << ": sema count = " << m_count << endl; sem.Post(); cout << get_curtime() << ", " << name << ": sema post and sleep 1 sec" << endl; sleep(1); }
cout << get_curtime() << ", " << name << ": end" << endl;}

3.5.6、编写子线程B

首先定义有名信号量,信号量数目可以随意设置。

其次,通过Open()打开有名信号量,可以与main()的有名信号量共享同一个信号量。

最后,通过TryWait()和Post()来获取释放信号量。

static void funcB(const string &name){ OHOS::NamedSemaphore sem(STRING_NAME_SEMAPHORE, 1);
cout << get_curtime() << ", " << name << ": start\n"; // 打开一个已经创建的有名信号量文件 if (!sem.Open()) { cout << get_curtime() << ", " << name << ": sema open failed" << endl; return; }
for (int i = 0; i < 5; i++) { cout << get_curtime() << ", " << name << ": sema trywait..." << endl; if (sem.TryWait()) { cout << get_curtime() << ", " << name << ": sema trywait success" << endl; m_count += 10; usleep(1000 * 1000 * 1); cout << get_curtime() << ", " << name << ": sema count = " << m_count << endl; sem.Post(); cout << get_curtime() << ", " << name << ": sema post and sleep 1 sec" << endl; } else { cout << get_curtime() << ", " << name << ": sema tryWait failed and sleep 1 sec" << endl; } sleep(1); }
cout << get_curtime() << ", " << name << ": end" << endl;}

3.5.7、编写子线程C

首先定义有名信号量,信号量数目可以随意设置。

其次,通过Open()打开有名信号量,可以与main()的有名信号量共享同一个信号量。

最后,通过TimedWait()和Post()来获取释放信号量。

static void funcC(const string &name){ OHOS::NamedSemaphore sem(STRING_NAME_SEMAPHORE, 1); struct timespec ts;
cout << get_curtime() << ", " << name << ": start\n";
// 打开一个已经创建的有名信号量文件 if (!sem.Open()) { cout << get_curtime() << ", " << name << ": sema open failed" << endl; return; } for (int i = 0; i < 5; i++) { clock_gettime(CLOCK_REALTIME, &ts); // 超时等待时间,1秒 ts.tv_sec += 1; cout << get_curtime() << ", " << name << ": sema timedwait 1 sec..." << endl; if (sem.TimedWait(ts)) { cout << get_curtime() << ", " << name << ": sema timedwait success" << endl; m_count += 100; usleep(1000 * 100); cout << get_curtime() << ", " << name << ": sema count = " << m_count << endl; sem.Post(); cout << get_curtime() << ", " << name << ": sema post" << endl; } else { cout << get_curtime() << ", " << name << ": sema timedwait failed and sleep 1 sec" << endl; sleep(1); } }
cout << get_curtime() << ", " << name << ": end" << endl;
}

4、编译步骤

进入OpenHarmony编译环境,运行如下命令:

hb build -f

将镜像烧录到开发板中。

5、运行结果

5.1、无名信号量

运行结果如下:

# utils_noname_semaphorethread_0: Sema Wait...thread_0: Sema Wait Successfulthread_0: Sema Postthread_1: Sema Wait...thread_1: Sema Wait Successfulthread_1: Sema Postthread_0: Sema Wait...thread_0: Sema Wait Successfulthread_0: Sema Postthread_2: Sema Wait...thread_2: Sema Wait Successfulthread_2: Sema Postthread_0: Sema Wait...thread_0: Sema Wait Successfulthread_0: Sema Postthread_1: Sema Wait...thread_1: Sema Wait Successfulthread_1: Sema Postthread_3: Sema Wait...thread_3: Sema Wait Successfulthread_3: Sema Postthread_2: Sema Wait...thread_0: Sema Wait Successfulthread_2: Sema Wait...thread_2: Sema Postthread_1: Sema Wait...thread_0: Sema Wait Successfulthread_0: Sema Postthread_1: Sema Wait Successfulthread_1: Sema Postthread_4: Sema Wait...thread_4: Sema Wait Successfulthread_4: Sema Postthread_3: Sema Wait...thread_3: Sema Wait Successfulthread_3: Sema Postthread_2: Sema Wait...thread_2: Sema Wait Successfulthread_2: Sema Postthread_0: Sema Wait...thread_0: Sema Wait Successfulthread_0: Sema Postthread_1: Sema Wait...thread_1: Sema Wait Successfulthread_1: Sema Postthread_4: Sema Wait...thread_4: Sema Wait Successfulthread_4: Sema Postthread_3: Sema Wait...thread_3: Sema Wait Successfulthread_3: Sema Postthread_2: Sema Wait...thread_2: Sema Wait Successfulthread_2: Sema Postthread_1: Sema Wait...thread_1: Sema Wait Successfulthread_1: Sema Postthread_4: Sema Wait...thread_4: Sema Wait Successfulthread_4: Sema Postthread_3: Sema Wait...thread_3: Sema Wait Successfulthread_3: Sema Postthread_2: Sema Wait...thread_2: Sema Wait Successfulthread_2: Sema Postthread_4: Sema Wait...thread_4: Sema Wait Successfulthread_4: Sema Postthread_3: Sema Wait...thread_3: Sema Wait Successfulthread_3: Sema Postthread_4: Sema Wait...thread_4: Sema Wait Successfulthread_4: Sema Postthreads stop#

5.2、有名信号量

运行结果如下:

# utils_name_semaphore2017-8-5 1924, thread_a: start2017-8-5 19:43:24, thread_b: start2017-8-5 19:43:24, thread_c: start2017-8-5 19:43:24, thread_a: sema wait...2017-8-5 19:43:24, thread_a: sema wait success2017-8-5 19:43:24, thread_b: sema trywait...2017-8-5 19:43:24, thread_b: sema tryWait failed and sleep 1 sec2017-8-5 19:43:24, thread_c: sema timedwait 1 sec...2017-8-5 19:43:25, thread_a: sema count = 12017-8-5 19:43:25, thread_c: sema timedwait failed and sleep 1 sec2017-8-5 19:43:25, thread_a: sema post and sleep 1 sec2017-8-5 19:43:25, thread_b: sema trywait...2017-8-5 19:43:25, thread_b: sema trywait success2017-8-5 19:43:26, thread_a: sema wait...2017-8-5 19:43:26, thread_c: sema timedwait 1 sec...2017-8-5 19:43:26, thread_b: sema count = 112017-8-5 19:43:26, thread_b: sema post and sleep 1 sec2017-8-5 19:43:26, thread_a: sema wait success2017-8-5 19:43:27, thread_c: sema timedwait failed and sleep 1 sec2017-8-5 19:43:27, thread_b: sema trywait...2017-8-5 19:43:27, thread_b: sema tryWait failed and sleep 1 sec2017-8-5 19:43:27, thread_a: sema count = 122017-8-5 19:43:27, thread_a: sema post and sleep 1 sec2017-8-5 19:43:28, thread_c: sema timedwait 1 sec...2017-8-5 19:43:28, thread_c: sema timedwait success2017-8-5 19:43:28, thread_b: sema trywait...2017-8-5 19:43:28, thread_a: sema wait...2017-8-5 19:43:28, thread_b: sema tryWait failed and sleep 1 sec2017-8-5 19:43:28, thread_c: sema count = 1122017-8-5 19:43:28, thread_c: sema post2017-8-5 19:43:28, thread_c: sema timedwait 1 sec...2017-8-5 19:43:28, thread_a: sema wait success2017-8-5 19:43:29, thread_b: sema trywait...2017-8-5 19:43:29, thread_b: sema tryWait failed and sleep 1 sec2017-8-5 19:43:29, thread_c: sema timedwait failed and sleep 1 sec2017-8-5 19:43:29, thread_a: sema count = 1132017-8-5 19:43:29, thread_a: sema post and sleep 1 sec2017-8-5 19:43:30, thread_b: sema close2017-8-5 19:43:30, thread_c: sema timedwait 1 sec...2017-8-5 19:43:30, thread_c: sema timedwait success2017-8-5 19:43:30, thread_a: sema wait...2017-8-5 19:43:31, thread_c: sema count = 2132017-8-5 19:43:31, thread_c: sema post2017-8-5 19:43:31, thread_c: sema close2017-8-5 19:43:31, thread_a: sema wait success2017-8-5 19:43:32, thread_a: sema count = 2142017-8-5 19:43:32, thread_a: sema post and sleep 1 sec2017-8-5 19:43:33, thread_a: sema wait...2017-8-5 19:43:33, thread_a: sema wait success2017-8-5 19:43:34, thread_a: sema count = 2152017-8-5 19:43:34, thread_a: sema post and sleep 1 sec2017-8-5 19:43:35, thread_a: sema closethreads stop#

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编译
    +关注

    关注

    0

    文章

    687

    浏览量

    34935
  • 线程
    +关注

    关注

    0

    文章

    508

    浏览量

    20753
  • OpenHarmony
    +关注

    关注

    31

    文章

    3924

    浏览量

    20697
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    OpenHarmony TSC 2025年度技术课题发布(截至10月)

    、学者们揭榜课题、参与分解课题,共同推动开源鸿蒙终端操作系统的技术突破与生态繁荣。详见下表: 挑战方向 挑战课题 挑战方向1:以用户为中心、场景感知的应用软件新形态 面向OpenHarmony平台的C/
    的头像 发表于 11-05 19:12 1054次阅读

    技能+1!如何在树莓派上使用C++控制GPIO?

    和PiGPIO等C++可用于编程控制树莓派的GPIO引脚。它提供了更好的性能和控制能力,非常适合对速度和精度要求较高的硬件项目。在树莓派社区中,关于“Python
    的头像 发表于 08-06 15:33 3563次阅读
    技能+1!如何在树莓派上使用<b class='flag-5'>C++</b>控制GPIO?

    C++ 与 Python:树莓派上哪种语言更优?

    Python是树莓派上的首选编程语言,我们的大部分教程都使用它。然而,C++在物联网项目中同样广受欢迎且功能强大。那么,在树莓派项目中选择哪种语言更合适呢?Python因其简洁性、丰富的和资源而被
    的头像 发表于 07-24 15:32 627次阅读
    <b class='flag-5'>C++</b> 与 Python:树莓派上哪种语言更优?

    【重要通知】OpenHarmony主干平台开发板选型提报倒计时(参考工具发布)

    各位伙伴好: 鉴于当前开源鸿蒙标准系统的主线验证平台(RK3568)在性能上已难以满足未来几年的发展需求。为确保系统持续演进,现启动下一代主力验证平台的规划工作。 经过初步调研,我们筛选出四个候选
    发表于 07-24 09:17

    OpenHarmony 2025年度技术课题发布

    课题共计6道。热切期待各界的专家、学者们揭榜课题、参与分解课题,共同推动OpenHarmony终端操作系统的技术突破与生态繁荣。详见下表: 挑战方向 挑战课题 挑战方向1:以用户为中心、场景感知的应用软件新形态 面向OpenHarmon
    的头像 发表于 07-23 20:57 581次阅读

    贡献 OpenHarmony 关键配置

    # 贡献 OpenHarmony 关键配置 #自研框架#ArkUI-X#三方框架#OpenHarmony#HarmonyOS ## 创建第三方 - 打开 DevEco Stud
    发表于 05-28 13:46

    一文带你了解KaihongOS标准系统的技术架构、子系统系统应用、典型特性以及支持的设备类型

    分布式软总线子系统 2.10.1 子系统概述 KaihongOS标准系统软件是基于OpenHarmony开发的新时代万物互联的操作系统
    发表于 04-23 07:17

    C++学到什么程度可以找工作?

    管理、引用、面向对象编程(与对象、继承、多态)、模板和STL(标准模板)等。 2. **数据结构与算法**:能够高效地实现并使用各种数据结构(如数组、链表、栈、队列、树、图等)和算法(如排序、查找
    发表于 03-13 10:19

    基于OpenHarmony标准系统C++公共基础案例:ThreadPoll

    1、程序简介该程序是基于OpenHarmony标准系统C++公共基础的线程池处理:Thre
    的头像 发表于 02-10 18:09 594次阅读
    基于<b class='flag-5'>OpenHarmony</b><b class='flag-5'>标准系统</b>的<b class='flag-5'>C++</b><b class='flag-5'>公共</b>基础<b class='flag-5'>类</b><b class='flag-5'>库</b>案例:ThreadPoll

    从Delphi、C++ Builder和Lazarus连接到MySQL数据

      从 Delphi、C++ Builder 和 Lazarus 连接到 MySQL 数据 MySQL 数据访问组件(MyDAC)是一个组件,提供从 Delphi 和 C++ Bu
    的头像 发表于 01-20 13:47 1313次阅读
    从Delphi、<b class='flag-5'>C++</b> Builder和Lazarus连接到MySQL数据<b class='flag-5'>库</b>

    从Delphi、C++ Builder和Lazarus连接到Oracle数据

    从 Delphi、C++ Builder 和 Lazarus 连接到 Oracle 数据 Oracle 数据访问组件 (ODAC) 是一个组件,它为 32 位和 64 位平台提供从 Delphi
    的头像 发表于 01-15 10:01 1343次阅读

    Spire.XLS for C++组件说明

    Spire.XLS for C++ 是一款专业的 C++ Excel 组件,可以用在各种 C++ 框架和应用程序中。Spire.XLS for C++ 提供了一个对象模型 Excel
    的头像 发表于 01-14 09:40 1293次阅读
    Spire.XLS for <b class='flag-5'>C++</b>组件说明

    EE-112:模拟C++中的实现

    电子发烧友网站提供《EE-112:模拟C++中的实现.pdf》资料免费下载
    发表于 01-03 15:15 0次下载
    EE-112:模拟<b class='flag-5'>C++</b>中的<b class='flag-5'>类</b>实现

    AKI跨语言调用神助攻C/C++代码迁移至HarmonyOS NEXT

    跨语言调用,成为开发者和厂商面临的重要挑战。为解决这一痛点,一款名为AKI (Alpha Kernel Interacting)的开源三方应运而生,它通过高效封装跨语言调用接口,帮助开发者将C
    发表于 01-02 17:08

    鸿蒙原生开源ViewPool在OpenHarmony社区正式上线

    近日,由伙伴参与共建的鸿蒙原生开源“ViewPool”在OpenHarmony社区正式上线。这个开发是基于OpenHarmony技术孵化的成果,充分发挥了平台的技术特性,同时融入了
    的头像 发表于 12-20 14:44 840次阅读