关于Android NDK libc++ libc++_shared、libstdc++的困惑

2024-02-01

我在尝试使用 Android NDK 23 (23.1.7779620) 构建一个简单的 C++ 库时感到非常困惑。我正在使用 CMake,这是一个非常简单的程序:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(mf) 
add_library(mf lib.cpp)

// lib.hpp
#pragma once
#include <string>
std::string foo(std::string);

// lib.cpp
#include "lib.hpp"
std::string foo(std::string str) {
  return std::string{"test"} + str;
}

这是构建的命令行:

cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DANDROID_STL=c++_shared -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29  -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake .. 
cmake --build . -v
  • 第一个问题是我期望链接到libc++.so并不是libc++_shared.so。它们之间有什么区别?我读本文 https://developer.android.com/ndk/guides/cpp-support。但仍然没有解释之间的区别libc++ and libc++_shared
  • 第二个问题更糟糕,看来我正在使用 libstdc++!
  • 第三点,我认为clang的c++实现是在命名空间下的std::__1但我找不到类似的东西。

我知道使用 libc++_shared 因为这个命令:

$ readelf -d libmf.so

Dynamic section at offset 0x76e0 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++_shared.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libmf.so]

运行 nm 似乎我正在使用来自libstdc++:

$ nm -gDC libmf.so | grep '__ndk1'
0000000000003af0 T foo(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >)
                 U std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::append(char const*, unsigned long)
$ nm -gDC libmf.so | grep '__1'
$

Update

在这篇文章中解释了之间的区别libc++.so and libc++_shared.so


通过传递-DANDROID_STL=c++_shared对于您明确要求共享运行时而不是默认运行时的 CMake 调用。

正如中所解释的文档 https://developer.android.com/ndk/guides/cpp-support#ic,规则很简单:

  1. if all您的本机代码位于单个库中,请使用静态 libc++(默认),以便可以删除未使用的代码,并且您拥有尽可能小的应用程序包。
  2. 一旦你包含了一个额外的库——要么是因为你包含了来自其他地方的预编译库,要么你包含了一个恰好包含本机代码的 Android AAR 文件——你must切换到共享运行时。

这些规则的基本原理很简单:C++ 运行时具有某些全局数据结构,must被初始化一次并且must内存中只存在一次。如果您不小心加载了两个静态链接 C++ 运行时的库,那么您就会有(例如)两个冲突的内存分配器。 当您这样做时,这将导致崩溃free or delete由其他库分配的内存,或者如果您传递 C++ STL 对象,例如std::string跨越图书馆边界。

为了完整起见,在较旧的 NDK 中,libstdc++(GNU C++ 运行时)也包含在 NDK 中,但从 NDK r18 开始,情况不再如此。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于Android NDK libc++ libc++_shared、libstdc++的困惑 的相关文章

随机推荐

  • Haskell 中 zipWith fibonacci 的时间复杂度

    在 Haskell 中 斐波那契函数的规范 zipWith 实现是 fibs Integer fibs 1 1 zipWith fibs tail fibs 我很难分析这个的时间复杂度 谎言 n 尝试将其写在纸上 起初我认为它是指数级的 然
  • 在 Spyder IDE 中使用 Matplotlib 绘制内联或单独窗口

    当我使用 Matplotlib 绘制一些图形时 默认的内联绘图通常就可以了 但是 当我绘制一些 3D 图形时 我希望将它们放在单独的窗口中 以便可以启用旋转等交互 我可以在 Python 代码中配置哪个图形要内联显示以及哪个图形要在新窗口中
  • 在正则表达式中使用否定条件

    是否可以在 gsub 表达式中使用负匹配 我想替换以以下开头的字符串hello except那些开始于hello Peter my string gsub hello i 我应该放什么来代替 听起来你想要一个负面的前瞻 gt gt hell
  • Grails - 无法读取 org.grails.plugins:tomcat:zip:8.0.33 的工件描述符

    从今天早上开始 我似乎遇到了 grails 插件存储库的问题 使用 Grails 2 4 4 获取 证书中的主机名不匹配 jfrog io gt 或 jfrog io gt 或 BuildConfig 具有 在插件下构建 org grail
  • Spring Data Rest - 如何在 @RepositoryEventHandler 中接收标头

    我正在使用最新的 Spring Data Rest 并且正在处理该事件 创建之前 我的要求是还捕获提交给POST模型的端点 Client 但是 该界面存储库事件处理程序并没有暴露这一点 Component RepositoryEventHa
  • 将 CardView 置于仅包含一个元素的 RecyclerView 中

    我使用的 RecyclerView 包含带有 TextView 和 ImageView 的 CardView 每张卡代表一个城市 我还在每张卡片上都有一个 onClickListener 它可以引导我找到该城市的博物馆列表 Recycler
  • 如何使用 JSTL 循环遍历字符串中的每个字符?

    如何使用 JSTL 循环遍历字符串中的每个字符 棘手的使用fn substring 会做
  • Angular-Dart DI 库中的工厂注入

    在我的 Dart 应用程序中 我使用 MVP 模式和 Angular dart 依赖注入库 Angular di 在上面的示例中 我无法注入 MyView 或 MyPresenter 因为这是循环依赖项 class MyView MyPre
  • 术语:前向声明与函数原型

    对我来说 使用 C 编程语言时这些术语本质上是同义词 在实践中 我可能更喜欢文件内原型的 前向声明 而不是通过头文件包含的原型的 函数原型 但当你考虑预处理后会发生什么时 即使这也是人为的区别 也许我错过了一些东西 对于何时使用一个术语与另
  • 解构 Open Layers 3 地图

    所以 我使用 Open Layers 3 和 Ember js 来制作仪表板 并且我已经动态加载地图 但我希望它在我离开路线时被销毁 我发现的唯一东西是 map destroy 但它是针对旧版本的API 新版本中似乎没有 进入地图页面几次后
  • 取消设置 git 配置

    我在 Mac 上使用 FileMerge 来查看差异 并设置为 git config global diff external bin git diff cmd sh 现在我不想再使用 FileMerge 如何恢复到之前的默认设置 Use
  • Zsh 无法正确自动完成我的 ssh 命令

    我在 ssh 自动完成方面遇到一些问题 我希望我的 zsh 在我的 ssh config 文件上自动完成 但到目前为止它只对 etc hosts 文件执行此操作 我发现如何通过添加此配置来不使用主机文件 zstyle completion
  • valgrind - 地址 ---- 是分配大小为 8 的块后的 0 字节

    首先 我知道similar已提出问题 但是 我想问一个关于真正原始 C 数据类型的更一般的简单问题 所以就是这样 In main c我调用一个函数来填充这些字符串 int main int argc char argv char host
  • 有没有API可以从wiki页面获取图像

    我想从维基百科页面获取主图像 我有所有维基百科实体名称 我从中创建维基链接并从该页面获取主图像 我尝试过 https github com richardasaurus wiki api https github com richardas
  • 嵌套的纯函数仍然是纯函数吗?

    根据定义 一个纯函数是纯的 如果 给定相同的输入 将始终返回相同的输出 不产生任何副作用 不依赖于外部状态 所以这是一个纯函数 function foo x return x 2 foo 1 2 foo 2 4 foo 3 6 这也将是一个
  • Angular 6 - 材质文本框浮动占位符不起作用

    我想使用 Angular 6 Material UI 组件来提供更高级的外观和感觉 我在测试程序下运行 但 mat 输入没有提供那种外观和感觉 参考 https material angular io components input ov
  • 有没有办法在 iOS 12.2 的 PWA 中使用 mailto: 或 message: 方案?

    我使用 Ionic 4 构建了一个 PWA 它有一个 联系 按钮 其中包含使用 mailto 方案的简单 href a href Contact a 当从主屏幕启动 PWA 时 这用于打开 iOS 12 1 中的本机邮件应用程序 自从我更新
  • 如何获取和/或覆盖 Mac OSX 中窗口的最小尺寸

    我想调整我的机器上的任何窗口的大小 这是我使用 AppleScript 完成的 使用图形用户界面脚本 http www macosxautomation com applescript uiscripting index html 该脚本类
  • 如何计算 JSON 数据中变量的总和?

    我编写了一个项目 其中字符串以相反的方式返回 PostMapping reverse public String reverseList RequestBody String string List
  • 关于Android NDK libc++ libc++_shared、libstdc++的困惑

    我在尝试使用 Android NDK 23 23 1 7779620 构建一个简单的 C 库时感到非常困惑 我正在使用 CMake 这是一个非常简单的程序 CMakeLists txt cmake minimum required VERS