Android NDK开发详解之针对中间件供应商的建议

Android NDK开发详解之针对中间件供应商的建议

      • 选择 API 级别和 NDK 版本
      • 使用 STL
      • 在 AAR 中分发原生库
      • 包含 JNI 库的 Java 中间件

分发使用 NDK 构建的中间件会引发其他问题,但应用开发者无需对此感到担心。预构建库会为用户提供一些实现选项。

选择 API 级别和 NDK 版本

您的用户无法使用低于您的级别的 minSdkVersion。如果用户的应用需要在 API 21 上运行,您就无法针对 API 24 构建应用。您可以针对低于用户级别的 API 级别构建库。您可以针对 API 16 构建应用,并保持与 API 21 用户兼容。

各个 NDK 版本大部分是相互兼容的,但版本间的变更偶尔也会破坏兼容性。如果您确定您的所有用户使用的都是相同版本的 NDK,那么您最好也使用与用户相同的版本。否则,请使用最新版本。

使用 STL

如果您正在编写 C++ 和使用 STL,并且要分发共享库,那么您在 libc++_shared 和 libc++_static 之间的选择会对您的用户产生影响。如果您要分发共享库,则必须使用 libc++_shared,或确保共享库不会公开 libc++ 的符号。要实现此目标,最好的方法是通过版本脚本明确声明您的 ABI 界面(这也有助于将实现细节保持私有状态)。例如,一个简单的算术库可能拥有以下版本脚本:
注意:如果您要分发静态库,无论是选择静态 STL 还是共享 STL 都无关紧要,因为静态库中未关联任何内容。用户可以关联他们在应用中选择的任何内容。但用户必须关联一些内容,即使是针对仅限 C 的使用方。因此,请务必将这一点记录为必须采取的措施,并记录用于构建的 NDK 版本,以防 STL 版本之间存在不兼容的情况。


LIBMYMATH {
global:add;sub;mul;div;# C++ symbols in an extern block will be mangled automatically. See# https://stackoverflow.com/a/21845178/632035 for more examples.extern "C++" {"pow(int, int)";}
local:*;
};

首选方式应为版本脚本,因为这是控制符号可见性的最可靠方式。这对于所有共享库(无论是否是中间件)来说都是最佳做法,因为这可以防止您的实现细节被公开,并能够缩短加载时间。

另一个可靠性较低的方式是在关联时使用 -Wl,–exclude-libs,libc++_static.a -Wl,–exclude-libs,libc++abi.a。这种方式的可靠性较低是因为它只会隐藏库中明确指定的符号,并且不会为未使用的库报告诊断信息(库名称中的拼写错误不属于错误,并且用户应负责及时更新库列表)。此方式也不会隐藏您自己的实现细节。

在 AAR 中分发原生库

注意:本部分将介绍如何将 C/C++ API 分发给用户。如果原生库属于您的 Java API 的实现细节,请参阅包含 JNI 库的 Java 中间件部分。

Android Gradle 插件可以导入在 AAR 中分发的原生依赖项。如果您的用户使用的是 Android Gradle 插件,这将是他们使用您的库的最简单的方式。

原生库可以通过 AGP 打包到 AAR 中。如果您的库已经通过 externalNativeBuild 构建,这便是最简单的方法。

非 AGP build 可以使用 ndkports,或按照 Prefab 文档中的说明执行手动打包,以便创建 AAR 的 prefab/ 子目录。

包含 JNI 库的 Java 中间件

包含 JNI 库(即包含 jniLibs 的 AAR)的 Java 库需要小心谨慎地处理,这样它们包含的 JNI 库才不会与用户应用中的其他库发生冲突。例如,如果 AAR 包含的 libc++_shared.so 版本不同于应用使用的 libc++_shared.so 版本,那么只有其中一个版本会安装到 APK,并且这可能会引发不可靠的行为。
警告:错误 141758241:较旧版本的 Android Gradle 插件目前不会诊断这种错误。系统将任意选择一个同名库打包到 APK 中。

最可靠的解决方案是确保 Java 库中的 JNI 库不超过一个(这个建议也适用于应用)。包括 STL 在内的所有依赖项都应静态关联到实现库,并且应通过版本脚本强制执行 ABI 界面。例如,包含 JNI 库 libfooimpl.so 的 Java 库 com.example.foo 应使用以下版本脚本:

LIBFOOIMPL {
global:JNI_OnLoad;
local:*;
};

本示例按照 JNI 提示中所述的说明,在 JNI_OnLoad 中使用 registerNatives 来确保尽量少公开 ABI 界面,并最大限度缩短库的加载时间。

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

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

相关文章

C++前缀和算法的应用:统计上升四元组

C前缀和算法的应用:统计上升四元组 本文涉及的基础知识点 C算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 题目 给你一个长度为 n 下标从 0 开始的整数数组 nums ,它包含 1 到 n 的所有数字,请你返回上…

IT行业就业分析

1. IT技术发展背景及历程介绍 2. IT行业的就业方向有哪些? IT技术发展背景及历程介绍: IT技术的发展背景和历程可以追溯到上世纪40年代,以下是IT技术的主要发展阶段: 1.计算机的发展:二战期间,计算机作…

DXF文件写入多边形和名称属性,可在Global Mapper和ArcGIS打开

DXF文件写入多边形和名称属性,可在Global Mapper和ArcGIS打开 目标效果 为了实现下图的效果,学习了一下dxf格式的相关内容。 官方文档价值很高,但是结合实例.dxf文件看学习起来更快。 免费下载实例 下面将介绍dxf文件的格式规范&#xff0…

Elasticsearch:在你的数据上训练大型语言模型 (LLM)

过去的一两年,大型语言模型(LLM)席卷了互联网。 最近 Google 推出的 PaLM 2 和 OpenAI 推出的 GPT 4激发了企业的想象力。 跨领域构思了许多潜在的用例。 多语言客户支持、代码生成、内容创建和高级聊天机器人都是一些例子。 这些用例要求 LL…

AWK语言第二版 3.2啤酒评级

3.2 啤酒评级 我们的下一个数据集是大约160万种啤酒的评级,数据来源于 ratebeer.com,一个啤酒爱好者的网站。数据集太大,通过逐行研究来确认它的特性是不可行的,所以我们要依赖像Awk这样的工具来探索并验证数据。 数据来自Kaggl…

Terraform 系列-使用Dynamic Blocks对Blocks进行迭代

系列文章 Terraform 系列文章Grafana 系列文章 概述 Terraform 系列文章 介绍了使用 Grafana Terraform Provider, 基于 Terraform 的 IaC 方法论, 来批量自动化创建 Grafana 的各类资源, 包括 Dashboard/Datasource 等. 现在有这么一个现实需求: 出于权限控制…

Ubuntu 22.04 安装 Terraform

Ubuntu 22.04 安装 Terraform 安装 Terraform 安装 Terraform sudo apt updatesudo apt install software-properties-common gnupg2 curlcurl https://apt.releases.hashicorp.com/gpg | gpg --dearmor > hashicorp.gpgsudo install -o root -g root -m 644 hashicorp.gpg…

shell_62.shell脚本生成一个标准的 SQL INSERT 语句

无论是将文件读入脚本,还是将数据从脚本输出到文件,都会用到文件重定向,这是一种很 常见的操作。本节中的示例脚本两种功能皆有。它会读取 CSV 格式的数据文件,输出 SQL INSERT 语句,并将数据插入数据库。 shell 脚本使…

数字展厅搭建平台要具备哪些功能,如何选择数字展厅搭建平台

引言: 数字展厅搭建平什台是现代营销中不可或缺的重要工具之一。它可以帮助企业打造个性化、多媒体、互动性强的展示空间,吸引、引导和留住目标用户。在选择数字展厅搭建平台时,我们需要考虑各方面的功能和性能,以确保能够满足企业的需求并取…

面试算法47:二叉树剪枝

题目 一棵二叉树的所有节点的值要么是0要么是1,请剪除该二叉树中所有节点的值全都是0的子树。例如,在剪除图8.2(a)中二叉树中所有节点值都为0的子树之后的结果如图8.2(b)所示。 分析 下面总结什么样的节…

全网公开电商数据的采集重点

数据的采集是根据需求而定的,品牌会做数据采集的原因,一般与内部营销、渠道管控有关,如需要做价格管控时,需要先采集价格,这就需要对数据进行采集,包括价格、促销信息,又或者是需要做行业分析、…

typing.Union` 标注一多种变量类型

typing.Union 标注一多种变量类型 typing.Union 是Python typing 模块中用于标注一个变量可以是多种类型之一的类型提示。在Python 3.10版本及以后,推荐使用 | 运算符代替 Union。不过,在详细介绍 Union 的用法前,值得注意的是在大多数情况下…

PHP连接SQLServer echo输出中文汉字显示乱码解决方法

1、查询结果有中文会显示乱码。 解决方法一&#xff08;较简单&#xff0c;建议使用&#xff09;&#xff1a; 在php文件最开头写上&#xff1a; header(Content-type: text/html; charsetUTF8); // UTF8不行改成GBK试试&#xff0c;与你保存的格式匹配 <?php header(&q…

matab读取包含struct混合类型的mat文件转为txt文件

现有一个mat文件&#xff0c;其内容如下&#xff1a; 目标&#xff1a;要将data.mat中的Obs_Iridium_A转为文本格式。 分析&#xff1a; data.mat里面包含了4个struct结构的成员&#xff0c;Obs_Iridium_A是其中之一&#xff0c;Obs_Iridium_A为1*7496维&#xff0c;7496代表…

波浪理论第3波anzo capital昂首资本3个方法3秒确认

要想通过波浪理论在交易中赚取最大利润&#xff0c;确认第三波必不可少&#xff0c;因为第三波通常是趋势中最大和最强的一波&#xff0c;今天anzo capital昂首资本3个方法3秒确认。 首先&#xff0c;第一个确认方法—斜率。 通常&#xff0c;第三波的斜率会比第一波更陡峭&a…

Linux内核是如何创建进程?

目录 1.Linux如何创建进程 2.fork函数原理 2.1 fork函数原型 2.2 fork函数实现原理 2.3 父子进程虚拟地址空间&#xff08;mm_struct&#xff09;之间的关系 2.4 写时拷贝&#xff08;copy-on-write&#xff09;技术 2.5 父子进程如何共享文件&#xff08;files_struct&…

06、Caused by: java.nio.charset.MalformedInputException: Input length = 1

目录 问题&#xff1a;原因&#xff1a;解决方法&#xff1a; 问题&#xff1a; Caused by: java.nio.charset.MalformedInputException: Input length 1 原因&#xff1a; 应该是中文有哪些文字导致的。 yml 编码格式出错 解决方法&#xff1a; 直接这里把GBK改成 utf-8…

unordered系列关联式容器--哈希结构详细讲解及使用示例

目录 unordered系列关联式容器unordered_map 哈希哈希概念哈希函数直接定址法&#xff1a;除留余数法&#xff1a; 哈希冲突解决哈希冲突闭散列&#xff1a;开散列&#xff1a; unordered系列关联式容器 之前讲解在C98中STL提供了底层为红黑树结构的一系列关联式容器&#xff…

vue按需加载组件

写vue时候&#xff0c;通常会进行路由懒加载&#xff0c;如下&#xff1a; {path: /settlementCenter/offCompensationSettlement,name: XXX,component: () >import(/view/settlementCenter/settlement/offCompensationSettlement.vue),meta: {}},写vue代码页面时&#xff0…

Nginx域名重定向(如何访问的域名和实际的数据请求路径不同,可解决前端跨域)

感情需要被抑制&#xff0c;不能泛滥… 当需要将一个域名重定向到另一个域名并且用户仍然看到原始域名时&#xff0c;Nginx是一个强大的工具。这种场景通常涉及到反向代理或重写URL的技巧。在本篇博客中&#xff0c;我们将详细介绍如何使用Nginx来实现这个目标&#xff0c;以及…