Android NDK学习 <五> C++ 支持

作者: Sam (甄峰) <wbr><span>sam_code@hotmail.com</span><br><br><strong><span style="color:rgb(153,0,48); line-height:21px; word-wrap:normal; word-break:normal">0.基础知识:</span></strong><br><span>Android Platform提供一个非常小的C++ runtime 支持库(</span><span>/system/lib/libstdc++</span><span>)和头文件。</span><br><span>但此System C++库支持非常有限,不支持以下 :</span><br><pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr><span></span>- Standard C++ Library support (except a few trivial headers).<span></span></wbr></span> <span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr><span></span>- C++ exceptions support<span></span></wbr></span> <span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr><span></span>- RTTI support</wbr></span> <span style="line-height:normal; word-wrap:normal; word-break:normal">但Android也提供几个其它的选择。可以通过Application.mk中</span><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>APP_STL</strong><span></span>作设置</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">(见</span><span style="font-family:微软雅黑,黑体; color:rgb(54,100,157); text-align:left; line-height:20px; background-color:rgb(254,254,254); word-wrap:normal; word-break:normal"><span style="font-size:12px; line-height:18px; word-wrap:normal; word-break:normal">Android<wbr>NDK学习<wbr>&lt;四&gt;<wbr>Application.mk简介</wbr></wbr></wbr></span></span><span style="line-height:normal; word-wrap:normal; word-break:normal">)。</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">设置选项有如下选择: </span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><strong><span style="line-height:normal; word-wrap:normal; word-break:normal">system -&gt; Use the default minimal system C++ runtime library.<span></span></span> <span style="line-height:normal; word-wrap:normal; word-break:normal">gabi++_static -&gt; Use the GAbi++ runtime as a static library.<span></span></span> </strong><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>gabi++_shared -&gt; Use the GAbi++ runtime as a shared library.<span></span> stlport_static -&gt; Use the STLport runtime as a static library.<span></span> stlport_shared -&gt; Use the STLport runtime as a shared library.<span></span> gnustl_static -&gt; Use the GNU STL as a static library.<span></span> gnustl_shared -&gt; Use the GNU STL as a shared library.</strong> 当APP_STL没有设置时,则缺省使用system的这个。 以上几种C++库能力集对:</span><span style="line-height:normal; word-wrap:normal; word-break:normal">C++<wbr></wbr></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr>Exceptions</wbr></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr><span></span>,</wbr></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr>C++<wbr></wbr></wbr></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr>RTTI</wbr></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><wbr><span></span>,</wbr></span><span style="line-height:normal; word-wrap:normal; word-break:normal">Standard Library支持分别如下: </span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">system no no no<span></span> gabi++ no yes no<span></span> stlport no yes yes<span></span> gnustl yes yes yes <strong><span style="color:rgb(153,0,48); line-height:21px; word-wrap:normal; word-break:normal">1. 各Runtime简介</span></strong>: <strong>1.1:System Runtime</strong>: Android提供的C++ Runtime,它只提供几个非常少的C++ 标准头文件。如果使用它,</pre> <pre style="white-space:pre-wrap; word-wrap:break-word">则应用程序二进制自动的链接此Android系统<span style="line-height:normal; word-wrap:normal; word-break:normal">libstdc++。 </span> 提供的头文件只有以下这些: </pre> <pre style="white-space:pre-wrap; word-wrap:break-word">cassert cctype cerrno cfloat climits cmath csetjmp csignal cstddef cstdint cstdio </pre> <pre style="white-space:pre-wrap; word-wrap:break-word">cstdlib cstring ctime cwchar new stl_pair.h typeinfo utility 不支持:<span style="line-height:normal; word-wrap:normal; word-break:normal">std::string or std::vector.</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><strong>1.2:</strong><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>GAbi++ runtime</strong>: 这是另一个小的C++ runtime, 与System C++ 提供同样多的头文件。但它支持RTTI。 现在已经很少用了。 <strong>1.3:<wbr></wbr></strong></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>STLport runtime</strong>: STLport(</span><span style="line-height:normal; word-wrap:normal; word-break:normal">http://www.stlport.org</span><span style="line-height:normal; word-wrap:normal; word-break:normal">)的Android 移植版。</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">提供完整的C++ 标准库头文件,</span><span style="line-height:normal; word-wrap:normal; word-break:normal">支持RTTI,但不支持</span><span style="line-height:normal; word-wrap:normal; word-break:normal">EXCEPTIONS.</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">(不支持异常很麻烦,就需要改不少代码) 静态动态均支持: </span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">APP_STL := stlport_shared<span></span></span> <span style="line-height:normal; word-wrap:normal; word-break:normal">APP_STL := stlport_static</span> <span style="line-height:normal">1.4:</span><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>GNU STL runtime</strong>: GNU 标准的C++ library. 支持更多特性。</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">库名叫:</span><span style="line-height:normal; word-wrap:normal; word-break:normal">libgnustl_shared.so,</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">而不是其它平台通常的:libstdC++.so</span> <span style="line-height:normal"><span style="color:rgb(153,0,48); line-height:21px; word-wrap:normal; word-break:normal">2.其它事项</span></span><span style="line-height:normal; word-wrap:normal; word-break:normal">:</span> <span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>2.1: C++ Exceptions</strong>:</span> 自从<span style="line-height:normal; word-wrap:normal; word-break:normal">NDK r5,NDK Toolchain就支持异常,可是,所有C++ 代码都缺省使用</span><span style="line-height:normal; word-wrap:normal; word-break:normal">-fno-exceptions编译,为的是向前兼容。 为了Enable C++ Exceptions,可以作如下动作: 在Android.mk中: </span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">LOCAL_CPP_FEATURES += exceptions <wbr><span></span>(推荐) </wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">或者: LOCAL_CPPFLAGS += -fexceptions 或者在Application.mk中: </pre> <pre style="white-space:pre-wrap; word-wrap:break-word">APP_CPPFLAGS += -fexceptions <strong>2.2:</strong><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>RTTI support</strong>: 与异常类似,自动NDK r5, NDK ToolChain就支持RTTI,但在缺省情况下都是用</span><span style="line-height:normal; word-wrap:normal; word-break:normal">-fno-rtti来编译C++代码。 如果想Enable RTTI;<wbr></wbr></span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">在Andriod.mk中: LOCAL_CPP_FEATURES += rtti (推荐) 或者 LOCAL_CPPFLAGS += -frtti 或者在:Application.mk:<span></span> APP_CPPFLAGS += -frtti <strong>2.3:<wbr></wbr></strong><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>Static runtimes</strong>: 当工程只有一个动态库用到C++ library. 则其使用静态C++库没有问题。 但当工程中有多个动态库用到C++ library(或其它静态库)时,则问题来了,每个动态库会包含静态库进去。</span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">这就有问题了,因为在内存中,就有多份COPY,那全局变量等都会有问题。 所以,当工程中多个动态库链接C++ library时,不要使用静态C++库方式。 <strong>2.4:<wbr></wbr></strong></span><span style="line-height:normal; word-wrap:normal; word-break:normal"><strong>Shared runtimes</strong>: </span><span style="line-height:normal; word-wrap:normal; word-break:normal">在使用动态库时,则需要确保C++ 动态库在其它库之前被Load到内存。 例如: </span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">libfoo.so<span></span> libbar.so which is used by libfoo.so<span></span> libstlport_shared.so, used by both libfoo and libbar</pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal"> 则: </span></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">static<span></span> {<span></span> <wbr>System.loadLibrary("gnustl_shared");<wbr><wbr>System.loadLibrary("bar");<span></span> <wbr>System.loadLibrary("foo");<span></span> <wbr>} 有一点需要注意: 因为C++ 程序调用xxx-xxx-g++编译,所以使用C++命名规范命名 符号,这样,Java JNI程序就找不到对应符号了。 所以需要添加: </wbr></wbr></wbr></wbr></wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">#ifdef <wbr><span></span>__cplusplus</wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">extern <wbr><span></span>"C"{</wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">#endif <em>function 声明。</em> </pre> <pre style="white-space:pre-wrap; word-wrap:break-word"></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">#ifdef <wbr><span></span>__cplusplus</wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">}</pre> <pre style="white-space:pre-wrap; word-wrap:break-word">#endif</pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><span style="line-height:normal; word-wrap:normal; word-break:normal">3. 对std::wstring支持:</span> <span style="line-height:normal; word-wrap:normal; word-break:normal">在NDK R7中,如果不做处理,则std::wstring会报未定义。</span> <span style="line-height:normal; word-wrap:normal; word-break:normal">于是Sam查找之:</span> <span style="line-height:normal; word-wrap:normal; word-break:normal">在:android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include/bits/stringfwd.h </span> </pre> <pre style="white-space:pre-wrap; word-wrap:break-word">#ifdef _GLIBCXX_USE_WCHAR_T</pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><wbr><span></span>template&lt;&gt; struct char_traits&lt;wchar_t&gt;;</wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"></pre> <pre style="white-space:pre-wrap; word-wrap:break-word"><wbr><span></span>typedef basic_string&lt;wchar_t&gt; wstring;</wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">#endif 所以,如果想要支持wstring,则需要定义<wbr><strong>_GLIBCXX_USE_WCHAR_T</strong></wbr></pre> <pre style="white-space:pre-wrap; word-wrap:break-word">于是:在Android.mk中, 在<span style="text-align:left; line-height:normal; background-color:rgb(254,254,254); color:rgb(73,73,73)">LOCAL_CXXFLAGS,LOCAL_CFLAGS中添加: -D_GLIBCXX_USE_WCHAR_T </span>即可支持wstring.<span></span> 更新:Sam发现,wstring在R7C版本中,编译虽然没有问题,但链接时会报错。 只有替换了NDK R8之后,才真正没有问题了。</pre> </wbr>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值