Android Studio NDK 入门教程(7)--被NDK支持的C++运行库

概述 Android 默认使用的是最小系统c++运行库,功能十分有限。并且不便于代码移植,毕竟STL在大部分代码中都有使用。
NDK支持哪几种C++运行库

Name 解释 特征
libstdc++ (default) The default minimal system C++ runtime library. N/A
gabi++_static The GAbi++ runtime (static). C++ Exceptions and RTTI
gabi++_shared The GAbi++ runtime (shared). C++ Exceptions and RTTI
stlport_static The STLport runtime (static). C++ Exceptions and RTTI; Standard Library
stlport_shared The STLport runtime (shared). C++ Exceptions and RTTI; Standard Library
gnustl_static The GNU STL (static). C++ Exceptions and RTTI; Standard Library
gnustl_shared The GNU STL (shared). C++ Exceptions and RTTI; Standard Library
c++_static The LLVM libc++ runtime (static). C++ Exceptions and RTTI; Standard Library
c++_shared The LLVM libc++ runtime (shared). C++ Exceptions and RTTI; Standard [Library]
来源:Android NDK Developer
显然如果你要使用vector、map、string等,你必须指定一个支持Standard Library 的C++运行库。他们在ndk-bundle中对应的文件夹是:\sources\cxx-stl\
如何指定运行库 这里要说一下共享库和静态库的区别。共享库直观上的讲就是多个软件用一个库文件,因此内存里只会存在一份代码。而静态库就是各用各的。他们之间各有好处。这里如果使用share结尾的运行库,那么运行库就不会打包到你的so里,程序运行的时候会装载Android系统上自带的库。当然如果这台Android设备/system/libs下没有这个库,那么程序就会崩溃。但个人认为最好还是使用共享库,因为这会减小生成so的大小。
Android.mk中使用 给APP_STL标签指定对应的值(上表中的Name字段)即可。如果没有指定,即使用默认的libstdc++,这里需要注意一点,无论静态还是共享都只能指定一个运行库。
//use gnustl_static APP_STL := gnustl_static //use gnustl_shared APP_STL := gnustl_shared

【Android Studio NDK 入门教程(7)--被NDK支持的C++运行库】如果要使用特征中的C++ Exceptions则还需要显示指定CPPFLAG:
APP_CPPFLAGS += -fexceptions

如果要使用特征中的RTTI则还需要显示指定CPPFLAG:
APP_CPPFLAGS += -frtti

Gradle配置 在Gradle中stl标签等价于APP_STL,cppFlags标签等价于APP_CPPFLAGS:
stl "stlport_share" cppFlags "-frtti" //实验版gradle cppFlags.add("-frtti")

关于使用静态还是共享库的官方建议
  • Static Runtime
    链接C++的静态库到多个二进制可能会导致意外的行为。例如,您可能会遇到:
    • 一个库分配的内存,而在其他释放,造成内存泄漏或堆损坏。
    • libfoo抛出的异常而在libbar中捕获,这将引起你的应用崩溃。
    • std::cout的缓冲可能不会正确的工作。
    此外,如果您链接两个共享库或一个共享库并针对相同的静态运行环境,那么最终每个二进制文件都将会存在一份静态库的拷贝。具有运行时代码多个实例是因为某些全局变量的重复运行期使用或内部提供的问题。这个问题并不适用于包括单个共享库的一个项目。例如,您可以针对性链接stlport_static,并期待您的应用程序正确运行。如果你的项目需要多个共享库模块,我们建议您使用C++运行时的共享库。
  • Shared runtimes
    如果您的应用程序针对一个版本的Android早于Android 4.3的(API 18),并使用给定的C++运行时的共享库,必须依赖于它的任何其他库之前加载共享库。
    例如, 一个应用可能有如下库:
libfoo.so libbar.so //在libfoo中使用 libstlport_shared.so //在libfoo和libbar中使用 //你必须根据其依赖关系对它们进行加载 static { System.loadLibrary("stlport_shared"); System.loadLibrary("bar"); System.loadLibrary("foo"); }

提示: 调用System.loadLibrary()不要使用库的后缀,即去掉.so后缀。
扩展知识
  • Android 稳定的NDK系统API
  • 如何使用预编译库

    推荐阅读