鸿蒙应用框架开发【dlopen加载so库并获取Rawfile资源】 NDK

dlopen加载so库并获取Rawfile资源

介绍

本示例中主要介绍在TaskPool子线程中使用dlopen加载so库,以及如何使用Native Rawfile接口操作Rawfile目录和文件。功能包括文件列表遍历、文件打开、搜索、读取和关闭Rawfile。

效果预览

1

使用说明

应用界面中展示了Rawfile相关的接口调用,包括获取resources/rawfile目录下的文件、对应的rawfile文件内容、对应rawfile文件的descriptor。其中使用到的功能包括文件列表遍历、文件打开、搜索、读取和关闭Rawfile。

工程目录

├──entry/libs/                             // 需要加载的.so文件
│  ├──arm64-v8a
│  │  └──libentry.so
│  └──x86_64
│     └──libentry.so
├──entry/src/main/cpp/                     // native侧代码
│  ├──include
│  │  └──global_handlers.h                 // 包含全局对象global_handlers的头文件
│  ├──types
│  │  ├──libentry
│  │  │  ├──index.d.ts                     // 接口导出
│  │  │  └──oh-package.json5
│  │  └──libpreloadso
│  │     ├──index.d.ts                     // 接口导出
│  │     └──oh-package.json5
│  ├──CMakeLists.txt                       // 编译脚本
│  ├──global_handlers.cpp                  // 定义全局对象global_handlers
│  ├──preloadso.cpp                        // preload接口
│  └──rawfile_demo.cpp                     // 调用native接口
├──entry/src/main/ets                      // ArkTS侧代码
│  ├──entryability
│  │  └──EntryAbility.ets
│  ├──pages
│  │  └──Index.ets                         // 首页
│  └──utils
│     ├──Constants.ets                     // 预加载的so文件数组
│     ├──Logger.ets                        // 日志工具
│     └──TaskPool.ets                      // TaskPool子线程加载so库
└──entry/src/main/resources                // 应用静态资源目录└──rawfile                              // rawfile资源├──subrawfile│  └──rawfile2.txt├──rawfile.txt└──rawfile1.txt

具体实现

在TaskPool子线程中使用dlopen加载so库,将需要加载的.so文件放到工程文件libs中,在CMakeLists编译脚本中使用target_link_directories命令将包含这些库文件的目录添加到预加载库的链接目录,使用target_link_libraries命令将需要预加载的so库链接到项目中。 在Native层的Preload接口中,遍历传入的.so路径数组,使用dlopen函数加载库,并将句柄保存到global_handlers中。暴露Preload接口给ArkTS层使用,使其能够通过preload调用Native层的Preload接口。源码参考:[preloadso.cpp]

/** Copyright (c) 2024 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#include "napi/native_api.h"
#include <dlfcn.h>
#include "global_handlers.h"
#include <hilog/log.h>// Hilog parameters.
const int GLOBAL_RESMGR = 0xFF00;
const char *TAG = "[Preload]";static napi_value Preload(napi_env env, napi_callback_info info) {OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "Preload init");size_t argc = 1;napi_value args[1] = {nullptr};napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);napi_value result;napi_create_array(env, &result); // Create an array to hold the results.// Args[0] is the SO library path array.napi_valuetype valuetype;napi_typeof(env, args[0], &valuetype);if (valuetype != napi_object) {return nullptr;}// Obtains the length of the input SO library path array.uint32_t arrayLength;napi_get_array_length(env, args[0], &arrayLength);napi_value pathString;// Path for storing the SO library.char path[256];size_t pathLength;OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "Preload start");for (uint32_t i = 0; i < arrayLength; i++) {napi_get_element(env, args[0], i, &pathString);napi_status status = napi_get_value_string_utf8(env, pathString, path, sizeof(path), &pathLength);if (status != napi_ok) {// Processing the Failure of Obtaining the Path.OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, " Preload failed");continue;}// Use dlopen to dynamically load the SO library and return the handle of the SO library.void *handler = dlopen(path, RTLD_LAZY);if (handler == nullptr) {// Dlerror throws failure to load library.OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, " Preload failed");dlerror();continue;}// Save the handles to the global object global_handlers.global_handlers[std::string(path)] = handler;// Add the path of the successfully loaded library to the result array.napi_set_element(env, result, i, pathString);}OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "Preload finish");// Return the result array that is loaded successfully.return result;
}EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {napi_property_descriptor desc[] = {{"preload", nullptr, Preload, nullptr, nullptr, nullptr, napi_default, nullptr}};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_ENDstatic napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "preloadso",.nm_priv = ((void *)0),.reserved = {0},
};extern "C" __attribute__((constructor)) void RegisterPreloadsoModule(void) { napi_module_register(&demoModule); }

ArkTS层使用TaskPool创建子线程,通过preload接口调用Native侧的Preload接口,实现在TaskPool子线程中加载.so库,导出preloadSOByTaskPool函数。 在Ability的onCreate生命周期函数中,调用preloadSOByTaskPool开启子线程,完成so库的预加载。源码参考:[TaskPool.ets]

/** Copyright (c) 2024 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { taskpool } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import napi from 'libpreloadso.so';
import Constants from './Constants';
import { Logger } from './Logger';/*** Enable the taskpool subthread to preload .so files.* @param* @returns string[] Loaded so library.*/
@Concurrent
function preloadSO(): string[] {return napi.preload(Constants.LIBRARY_PATH_ARRAY);
}/*** Starts the taskpool sub-thread.* @param* @returns Promise<string[]> Asynchronously return the loaded so library.*/
export function preloadSOByTaskPool(): void {// Use new taskpool.Task () to create a task item and input the task execution function and required parameters.const task: taskpool.Task = new taskpool.Task(preloadSO);try {// Use taskpool.execute to put the function to be executed into the internal task queue of TaskPool for execution.taskpool.execute(task, taskpool.Priority.HIGH).then((res: Object) => {// Processing after the so library is preloaded.Logger.info('PreloadSOByTaskPool:' + JSON.stringify(res));}).catch((error: BusinessError) => {Logger.error('PreloadSOByTaskPool: execute failed, ' + error.toString());});} catch (err) {Logger.error('PreloadSOByTaskPool: execute failed, ' + (err as BusinessError).toString());}
}

在Native层定义对外接口为getFileList、getRawFileContent、getRawFileDescriptor,映射C++接口分别为GetFileList、GetRawFileContent、GetRawFileDescriptor。 通过获取Js的资源对象,并转为Native的资源对象,即可调用资源的Native接口,获取rawfile列表、rawfile文件内容以及rawfile描述符{fd, offset, length}。 在Js侧导入"libentry.so",通过getContext().resourceManager获取资源管理对象。调用src/main/cpp/types/libentry/index.d.ts中声明的接口,传入js的资源对象和相关参数获取对于rawfile相关资源信息。 源码参考:[rawfile_demo.cpp] 。

/** Copyright (c) 2024 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#include <js_native_api.h>
#include <js_native_api_types.h>
#include <vector>
#include "napi/native_api.h"
#include "rawfile/raw_file_manager.h"
#include "rawfile/raw_file.h"
#include "rawfile/raw_dir.h"
#include "hilog/log.h"const int GLOBAL_RESMGR = 0xFF00;
const char *TAG = "[Sample_rawfile]";
static napi_value GetFileList(napi_env env, napi_callback_info info) {OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "GetFileList Begin");size_t argc = 2;napi_value argv[2] = {nullptr};napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);napi_valuetype valueType;napi_typeof(env, argv[0], &valueType);NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);size_t strSize;char strBuf[256];napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);std::string filename(strBuf, strSize);RawDir *rawDir = OH_ResourceManager_OpenRawDir(mNativeResMgr, filename.c_str());int count = OH_ResourceManager_GetRawFileCount(rawDir);std::vector<std::string> tempArray;for (int i = 0; i < count; i++) {std::string filename = OH_ResourceManager_GetRawFileName(rawDir, i);tempArray.emplace_back(filename);}napi_value fileList;napi_create_array(env, &fileList);for (size_t i = 0; i < tempArray.size(); i++) {napi_value jsString;napi_create_string_utf8(env, tempArray[i].c_str(), NAPI_AUTO_LENGTH, &jsString);napi_set_element(env, fileList, i, jsString);}OH_ResourceManager_CloseRawDir(rawDir);OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);return fileList;
}namespace {
napi_value CreateJsArrayValue(napi_env env, std::unique_ptr<uint8_t[]> &data, long length) {napi_value buffer;napi_status status = napi_create_external_arraybuffer(env, data.get(), length, [](napi_env env, void *data, void *hint) { delete[] static_cast<char *>(data); },nullptr, &buffer);if (status != napi_ok) {OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Failed to create external array buffer");return nullptr;}napi_value result = nullptr;status = napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &result);if (status != napi_ok) {OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Failed to create media typed array");return nullptr;}data.release();return result;
}
} // namespacestatic napi_value GetRawFileContent(napi_env env, napi_callback_info info) {OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "GetFileContent Begin");size_t argc = 2;napi_value argv[2] = {nullptr};napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);napi_valuetype valueType;napi_typeof(env, argv[0], &valueType);NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);size_t strSize;char strBuf[256];napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);std::string filename(strBuf, strSize);RawFile *rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, filename.c_str());if (rawFile != nullptr) {OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "OH_ResourceManager_OpenRawFile success");}long len = OH_ResourceManager_GetRawFileSize(rawFile);std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(len);int res = OH_ResourceManager_ReadRawFile(rawFile, data.get(), len);OH_ResourceManager_CloseRawFile(rawFile);OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);return CreateJsArrayValue(env, data, len);
}namespace {
napi_value createJsFileDescriptor(napi_env env, RawFileDescriptor &descriptor) {napi_value result;napi_status status = napi_create_object(env, &result);if (status != napi_ok) {return result;}napi_value fd;status = napi_create_int32(env, descriptor.fd, &fd);if (status != napi_ok) {return result;}status = napi_set_named_property(env, result, "fd", fd);if (status != napi_ok) {return result;}napi_value offset;status = napi_create_int64(env, descriptor.start, &offset);if (status != napi_ok) {return result;}status = napi_set_named_property(env, result, "offset", offset);if (status != napi_ok) {return result;}napi_value length;status = napi_create_int64(env, descriptor.length, &length);if (status != napi_ok) {return result;}status = napi_set_named_property(env, result, "length", length);if (status != napi_ok) {return result;}return result;
}
} // namespacestatic napi_value GetRawFileDescriptor(napi_env env, napi_callback_info info) {OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "GetRawFileDescriptor Begin");size_t argc = 2;napi_value argv[2] = {nullptr};napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);napi_valuetype valueType;napi_typeof(env, argv[0], &valueType);NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);size_t strSize;char strBuf[256];napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);std::string filename(strBuf, strSize);RawFile *rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, filename.c_str());if (rawFile != nullptr) {OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "OH_ResourceManager_OpenRawFile success");}RawFileDescriptor descriptor;OH_ResourceManager_GetRawFileDescriptor(rawFile, descriptor);OH_ResourceManager_CloseRawFile(rawFile);OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);return createJsFileDescriptor(env, descriptor);
}EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {napi_property_descriptor desc[] = {{"getFileList", nullptr, GetFileList, nullptr, nullptr, nullptr, napi_default, nullptr},{"getRawFileContent", nullptr, GetRawFileContent, nullptr, nullptr, nullptr, napi_default, nullptr},{"getRawFileDescriptor", nullptr, GetRawFileDescriptor, nullptr, nullptr, nullptr, napi_default, nullptr}};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_ENDstatic napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = ((void *)0),.reserved = {0},
};extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }

涉及到的相关接口:

接口名描述
初始化native resource manager。NativeResourceManager *OH_ResourceManager_InitNativeResourceManager(napi_env env, napi_value jsResMgr)
打开指定rawfile目录。RawDir *OH_ResourceManager_OpenRawDir(const NativeResourceManager *mgr, const char *dirName)
获取指定rawfile目录下的rawfile文件数量。int OH_ResourceManager_GetRawFileCount(RawDir *rawDir)
获取rawfile名字。const char *OH_ResourceManager_GetRawFileName(RawDir *rawDir, int index)
打开指定rawfile文件。RawFile *OH_ResourceManager_OpenRawFile(const NativeResourceManager *mgr, const char *fileName)
获取rawfile文件大小。long OH_ResourceManager_GetRawFileSize(RawFile *rawFile)
读取rawfile文件内容。int OH_ResourceManager_ReadRawFile(const RawFile *rawFile, void *buf, size_t length)
释放rawfile文件相关资源。void OH_ResourceManager_CloseRawFile(RawFile *rawFile)
释放rawfile目录相关资源。void OH_ResourceManager_CloseRawDir(RawDir *rawDir)
获取rawfile的fd。bool OH_ResourceManager_GetRawFileDescriptor(const RawFile *rawFile, RawFileDescriptor &descriptor)
释放native resource manager相关资源。void OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager *resMgr)

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/385538.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024最新Uniapp的H5网页版添加谷歌授权验证

现在教程不少&#xff0c;但是自从谷歌升级验证之后&#xff0c;以前的老教程就失效了&#xff0c;现在写一个新教程以备不时之需。 由于众所周知的特殊原因&#xff0c;开发的时候一定注意网络环境&#xff0c;如果没有梯子是无法进行开发的哦~ clientID的申请方式我就不再进…

昇思MindSpore 应用学习-DCGAN生成漫画头像-CSDN

日期 心得 昇思MindSpore 应用学习-DCGAN生成漫画头像&#xff08;AI代码学习&#xff09; DCGAN生成漫画头像 在下面的教程中&#xff0c;我们将通过示例代码说明DCGAN网络如何设置网络、优化器、如何计算损失函数以及如何初始化模型权重。在本教程中&#xff0c;使用的动…

数据结构:二叉树(堆)的顺序存储

文章目录 1. 树1.1 树的概念和结构1.2 树的相关术语 2. 二叉树2.1 二叉树的概念和结构2.2 二叉树的特点2.3 特殊的二叉树2.3.1 满二叉树2.3.2 完全二叉树 2.4 二叉树的性质 3. 实现顺序结构二叉树3.1 堆的概念和结构3.2 初始化3.3 销毁3.4 插入数据3.5 向上调整算法3.6 删除数据…

如何查找下载安装安卓APK历史版本?

在安卓设备上&#xff0c;有时候我们可能希望安装某个软件的旧版本&#xff0c;可能是因为新版本不兼容、功能改变不符合需求或是其他原因。 安卓系统并不像iOS那样提供直观的历史版本下载界面。 不过&#xff0c;通过一些第三方市场和网站&#xff0c;我们仍然可以找到并安装…

【LLM】-08-搭建问答系统-语言模型,提问范式与 Token

目录 1、语言模型 1.1、训练过程&#xff1a; 1..2、大型语言模型分类&#xff1a; 1.3、指令微调模型训练过程&#xff1a; 2、Tokens 3、Helper function辅助函数 (提问范式) 4、计算token数量 1、语言模型 大语言模型&#xff08;LLM&#xff09;是通过预测下一个词…

【python】sklearn基础教程及示例

【python】sklearn基础教程及示例 Scikit-learn&#xff08;简称sklearn&#xff09;是一个非常流行的Python机器学习库&#xff0c;提供了许多常用的机器学习算法和工具。以下是一个基础教程的概述&#xff1a; 1. 安装scikit-learn 首先&#xff0c;确保你已经安装了Python和…

搜索引擎项目(四)

SearchEngine 王宇璇/submit - 码云 - 开源中国 (gitee.com) 基于Servlet完成前后端交互 WebServlet("/searcher") public class DocSearcherServlet extends HttpServlet {private static DocSearcher docSearcher new DocSearcher();private ObjectMapper obje…

Kettle下载安装

环境说明 虚拟机&#xff1a;Win7&#xff1b;MySql8.0 主机&#xff1a;Win11&#xff1b;JDK1.8&#xff1b;Kettle 9.4&#xff08;Pentaho Data Integration 9.4&#xff09;&#xff08;下载方式见文末&#xff09; 安装说明 【1】解压后运行Spoon.bat 【2】将jar包 复…

【Linux C | 网络编程】进程池退出的实现详解(五)

上一篇中讲解了在进程池文件传输的过程如何实现零拷贝&#xff0c;具体的方法包括使用mmap&#xff0c;sendfile&#xff0c;splice等等。 【Linux C | 网络编程】进程池零拷贝传输的实现详解&#xff08;四&#xff09; 这篇内容主要讲解进程池如何退出。 1.进程池的简单退…

聊聊基于Alink库的主成分分析(PCA)

概述 主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;是一种常用的数据降维和特征提取技术&#xff0c;用于将高维数据转换为低维的特征空间。其目标是通过线性变换将原始特征转化为一组新的互相无关的变量&#xff0c;这些新变量称为主成分&…

7月24日JavaSE学习笔记

序列化版本控制 序列化&#xff1a;将内存对象转换成序列&#xff08;流&#xff09;的过程 反序列化&#xff1a;将对象序列读入程序&#xff0c;转换成对象的方式&#xff1b;反序列化的对象是一个新的对象。 serialVersionUID 是一个类的序列化版本号 private static fin…

算法通关:006_1二分查找

二分查找 查找一个数组里面是否存在num主要代码运行结果 详细写法自动生成数组和num&#xff0c;利用对数器查看二分代码是否正确 查找一个数组里面是否存在num 主要代码 /*** Author: ggdpzhk* CreateTime: 2024-07-27*/ public class cg {//二分查找public static boolean …

戴着苹果Vision Pro,如何吃花生米

6月底苹果Vision Pro国内开售&#xff0c;我早早到官网预订了一台。选择必要的配件&#xff0c;输入视力信息&#xff0c;定制符合自己视力的蔡司镜片。确实贵。把主要配件和镜片配齐&#xff0c;要3万6&#xff0c;比Pico、META的眼镜贵一个数量级。 Vision Pro出来后&#x…

C++的STL简介(一)

目录 1.什么是STL 2.STL的版本 3.STL的六大组件 4.string类 4.1为什么学习string类&#xff1f; 4.2string常见接口 4.2.1默认构造 ​编辑 4.2.2析构函数 Element access: 4.2.3 [] 4.2.4迭代器 ​编辑 auto 4.2.4.1 begin和end 4.2.4.2.regin和rend Capacity: 4.2.5…

Q238. 除自身以外数组的乘积

思路 一开始想到的是按位乘 看了题解&#xff0c;思路是存i左边的乘积和 与 i右边的乘积和 代码一&#xff1a; 需要三次循环,需要额外空间 left和right数组 代码&#xff1a; public int[] productExceptSelf(int[] nums) {int[] left new int[nums.length];int[] right …

【爱上C++】list用法详解、模拟实现

文章目录 一&#xff1a;list介绍以及使用1.list介绍2.基本用法①list构造方式②list迭代器的使用③容量④元素访问⑤插入和删除⑥其他操作image.png 3.list与vector对比 二&#xff1a;list模拟实现1.基本框架2.节点结构体模板3.__list_iterator 结构体模板①模板参数说明②构…

基于Xejen框架实现的C# winform鼠标点击器、电脑按键自动点击器的软件开发及介绍

功能演示 文章开始之前&#xff0c;仍然是先来个视频&#xff0c;以便用户知道鼠标连点器的基本功能 软件主界面 多功能鼠标连点器 快速点击&#xff1a; 痕即鼠标点击器可以设定每秒点击次数&#xff0c;让您轻松应对高频点击需求。 切换时长&#xff0c;即每次动作之间的间…

大数据的数据质量有效提升的研究

大数据的数据质量有效提升是一个涉及多个环节和维度的复杂过程。以下是从数据采集、处理、管理到应用等方面&#xff0c;对大数据数据质量有效提升的研究概述&#xff1a; 一、数据采集阶段 明确采集需求&#xff1a;在数据采集前&#xff0c;需明确数据需求&#xff0c;包括…

leetocde662. 二叉树最大宽度,面试必刷题,思路清晰,分点解析,附代码详解带你完全弄懂

leetocde662. 二叉树最大宽度 做此题之前可以先做一下二叉树的层序遍历。具体题目如下&#xff1a; leetcode102二叉树的层序遍历 我也写过题解&#xff0c;可以先看看学习一下&#xff0c;如果会做层序遍历了&#xff0c;那么这题相对来说会简单很多。 具体题目 给你一棵…