NDK之CPLUSPLUS-SUPPORT(C++支持的android NDK)

免责申明(必读!):本翻译原稿来自ndk,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作!

本文翻译的是NDK-r9b中的CPLUSPLUS-SUPPORT.html,即"C++支持的android NDK"

在NDK中,android平台提供了一个非常小的C++运行时(runtime)支持库(/system/lib/libstdc++)以及相应的头文件。

默认的,'system'运行时(runtime)【没有】提供下面的功能:    

        。标准C++库的支持(除了几个不太重要(trivial)的头文件)
        。c++异常的支持
        。RTTI的支持

然而,NDK有提供很多的”帮助C++运行时(runtime)“,里面就有支持上面的那些功能,或者这些特性的子集。

选择你要用的运行时(runtime),在你的Application.mk中定义App_STL为以下中的一个值:
         system                     -> 使用默认最小的C++运行库.
         gabi++_static         -> 使用GAbi++的静态运行库.
         gabi++_shared      -> 使用GAbi++的动态运行库.
         stlport_static           -> 使用STLport的静态运行库.
         stlport_shared        -> 使用TLport的懂态运行库.
         gnustl_static           -> 使用GNU的静态运行库.
         gnustl_shared        -> 使用GNU的动态运行库.

如果你没有在你的Application.mk中定义APP_STL,默认为‘system’运行时。下面是一个用静态GNU STL的例子,加一行像这样子的:

         APP_STL := gnustd_static

对于你的Application.mk,你只需要选择一个C++运行时就可以使得你所有的代码都依赖于它了。混合动态库编译C++运行时是不可能的。

重要提示:在Android.mk中定义APP_STL是没有用的。

如果你没有使用NDK的编译系统,你还是可以用GNU STL的,更多细节,请看 STANDALONE-TOOLCHAIN 。

各个‘运行时’的能力如下所示:
 
                        C++        C++       Standard
                  Exceptions   RTTI       Library

    system        no            no           no
    gabi++        yes          yes         no
    stlport          yes          yes         yes
    gnustl          yes           yes         yes

-----------------------------------------------------------------------------------------

I. 运行时(Runtimes)概览

I.1. 系统运行时(System runtime):

系统运行时只提供了非常少的C++标准头文件。

Android平台提供了相应的C++运行时。如果你使用了这个,你的C++二进制将会自动的链接到系统libstdc++。它只提供了如下的头文件:
              cassert cctype cerrno cfloat climits cmath csetjmp csignal cstddef
              cstdint cssdio cstdlib cstring ctime cwchar cwchar new stl_pair.h typeinfo
              utility

除此之外的就不支持了,包括std::string 或者 std::vector


I.2. GAbi++运行时(GAbi++ runtime):

这是一个提供了跟系统运行时(System runtime)一样的头文件的新的简约的运行时,但是他额外的加入了对RTTI(Runtime Type Information)以及异常(exception)处理的支持。

如果你坚持(insist on)要用它,请读一下下面的”重要考虑“的“RTTI支持”和“静态运行时“部分。

I.3. STLport运行时(STLport runtime)

这是一个可以用用在Android的STLport(http://www.stlport.org)端口。它将为你提供一个完整的C++标准库(standard library)的头文件以及 RTTI 和 对异常(exception)处理的支持。

这是因为该库中加入了GAbi++的副本.

它可以作为静态和动态库。如果你要使用它,在你的Application.mk中选择下面其中的一行:
      APP_STL := stlport_shared
      APP_STL := stlport_static

注意最好使用‘stlport_shared’,原因在下面的”重要考虑“的”静态运行时“里有解释。

I.4. GNU STL 运行时(GNU STL runtime)

这个是GNU标准的C++库来着(亦称为:libstdc++-v3),提供了更多的特性。注意,在其他的平台,动态库
"libstdc++.so"的文件名是"libgnustl_shared.so".

如果你要使用它,请阅读一下下面的”c++ Exception支持“,”RTTI支持“以及”静态运行时考虑“部分。

-----------------------------------------------------------------------------------------------------

II. 重要考虑

II.1. C++ Exceptions 支持

从NDK r5开始,NDK toolchain 支持c++ exceptions,然而为了兼容前面版本的所有的C++代码默认用-fno-exceptions编译(即默认没有咯)。
要使用它,在你的Android.mk中,你可以使用

       LOCAL_CPP_FEATURES += exceptions

关于这个变量的更多细节到 ANDROID-MK 中查看

另一个启用的方法是在你的LOCAL_CPPFLAGS中定义(但是还是推荐用LOCAL_CPP_FEATURES更好)

       LOCAL_CPPFLAGS += -fexception

更简单的是,在你的Application.mk中加入一行,它会自动应用到你项目的所有模块中:

       APP_CPPFLAGS += -fexception

II.2. RTTI 支持

类似的,从NDK r5之后,NDK toolchain 也支持c++ RTTI(RunTime Type Information),然而为了兼容前面版本的所有的C++代码默认用-fno-rtti编译(即默认没有咯)。要使用它,加入下面的东西到你的模块中:

       LOCAL_CPP_FEATURES += rtti

也等同于:

       LOCAL_CPPFLAGS += -frtti

或者更简单的就是在你的Application.mk中这样写咯:

       APP_CPPFLAGS += -frtti

II.3. 静态运行时:

请记住,一个C++静态库变量最好是只被链接到一个二进制文件。这个的意思是如果你的项目只包含一个动态库,那么你可以的链接它,如:stlport_static,然后所有的东西都运行正常。

另一方面,如果你的项目有两个动态库(如 libfoo.so 以及 libbar.so),然后它们都链接到相同的静态库,然后它们两个在最终的二进制文件中都会有那个静态库的副本。这是有问题的,因为某些全局变量/内部提供运行时重复使用。

这就有可能是代码运行结果不正确,比如:
      。内存分配在一个库里面,然后被另一个库给释放掉了,或者败坏(corrupt)堆。
      。在libfoo.so中抛出的异常不能被libbar.so捕获(可能程序就简单的崩溃了)
      。std::cout的缓冲就不能正常的工作
 
换种说法,如果你的项目要求有几个动态库模块,那么C++ runtime选择动态库吧。

II.4. 动态运行库:

如果你的C++ runtime使用的是动态库,那么记住,你必须在你的应用运行时,在其它依赖该动态库之前加载完该库。

举个列子,考虑以下模块的情形
      。libfoo.so
      。libbar.so 被libfoo.so用到
      。libstlport_shared.so被上面两个都用到

你必须按上面相反的顺序加载那些库,如下:
      static {
                  System.loadLibrary("stlport_shared");
                  System.loadLibrary("bar");
                  System.loadLibrary("foo");
      }

注意你使用System.loadLibray()时不需要加前缀'lib'的,除非你指定了整个路径(full path):

     System.loadLibrary("/path/to/libstlport_shared.so")

这种用硬编码(hard-codes)的方式是不推荐的。


----------------------------------------------------------------------------------------------------------
III. 额外部分:

III.1. STLport-specific 问题

NDK为STLport提供了的预编译的静态库和动态库,但你可在你的环境下或你的Application.mk下定义下面的东西就可以强制使其重新编译了:

       STLPORT_FORCE_REBULID := true

STLport是在BSD风格的开放源代码许可协议发布的。更多详细内容,请参见source/cxx-stl/stlport/README

你可能感兴趣的:(ndk)