您的位置:首页 > 编程语言 > C语言/C++

Android NDK学习之六、C++ 支持

2015-11-27 18:15 281 查看


0.基础知识:

Android Platform提供一个非常小的C++ runtime 支持库(/system/lib/libstdc++)和头文件。

但此System C++库支持非常有限,不支持以下 :

- Standard C++ Library support (except a few trivial headers).

- C++ exceptions support

- RTTI support

但Android也提供几个其它的选择。

可以通过Application.mk中APP_STL 作设置(见Android NDK学习 <四> Application.mk简介)。

设置选项有如下选择:

system -> Use the default minimal system C++ runtime library.

gabi++_static -> Use the GAbi++ runtime as a static library.

gabi++_shared -> Use the GAbi++ runtime as a shared library.

stlport_static -> Use the STLport runtime as a static library.

stlport_shared -> Use the STLport runtime as a shared library.

gnustl_static -> Use the GNU STL as a static library.

gnustl_shared -> Use the GNU STL as a shared library.

当APP_STL没有设置时,则缺省使用system的这个。

以上几种C++库能力集对:C++ Exceptions , C++ RTTI ,Standard Library支持分别如下:

system no no no

gabi++ no yes no

stlport no yes yes

gnustl yes yes yes

刚才有网友提示stlport支持RTTI和异常,要说明一下,NDK是不断更新的。

所以在R7C时代,Google移植的STLport并不支持异常

(刚查了R8也还不支持异常,但在NDK R10中,stlport已经支持异常了)

同样,gabi++, 在R10版本内也已经支持RTTI和异常了。

谢谢网友(ttbtr)提示。


1. 各Runtime简介:

1.1:System Runtime:

Android提供的C++ Runtime,它只提供几个非常少的C++ 标准头文件。

如果使用它,则应用程序二进制自动的链接此Android系统libstdc++。

提供的头文件只有以下这些:

cassert cctype cerrno cfloat climits cmath csetjmp csignal

cstddef cstdint cstdio cstdlib cstring ctime cwchar new stl_pair.h typeinfo utility

不支持:std::string or std::vector.

1.2:GAbi++ runtime:

这是另一个小的C++ runtime, 与System C++ 提供同样多的头文件。

但它支持RTTI。 现在已经很少用了。

1.3: STLport runtime:

STLport(http://www.stlport.org)的Android 移植版。

提供完整的C++ 标准库头文件,支持RTTI,但不支持EXCEPTIONS.

(不支持异常很麻烦,就需要改不少代码)

静态动态均支持:

APP_STL := stlport_shared

APP_STL := stlport_static

1.4:GNU STL runtime:

GNU 标准的C++ library. 支持更多特性。

库名叫:libgnustl_shared.so,而不是其它平台通常的:libstdC++.so


2.其它事项:

2.1: C++ Exceptions:

自从NDK r5,NDK Toolchain就支持异常,

可是,所有C++ 代码都缺省使用-fno-exceptions编译,为的是向前兼容。

为了Enable C++ Exceptions,可以作如下动作:

在Android.mk中:

LOCAL_CPP_FEATURES += exceptions (推荐)

或者:

LOCAL_CPPFLAGS += -fexceptions

或者在Application.mk中:

APP_CPPFLAGS += -fexceptions

2.2:RTTI support:

与异常类似,自动NDK r5, NDK ToolChain就支持RTTI,

但在缺省情况下都是用-fno-rtti来编译C++代码。

如果想Enable RTTI;

在Andriod.mk中:

LOCAL_CPP_FEATURES += rtti (推荐)

或者

LOCAL_CPPFLAGS += -frtti

或者在:Application.mk:

APP_CPPFLAGS += -frtti

2.3: Static runtimes:

当工程只有一个动态库用到C++ library. 则其使用静态C++库没有问题。

但当工程中有多个动态库用到C++ library(或其它静态库)时,则问题来了,

每个动态库会包含静态库进去。这就有问题了,

因为在内存中,就有多份COPY,那全局变量等都会有问题。

所以,当工程中多个动态库链接C++ library时,不要使用静态C++库方式。

2.4: Shared runtimes:

在使用动态库时,则需要确保C++ 动态库在其它库之前被Load到内存。

例如:

libfoo.so

libbar.so which is used by libfoo.so

libstlport_shared.so, used by both libfoo and libbar

则:

static

{

System.loadLibrary("gnustl_shared");

System.loadLibrary("bar");

System.loadLibrary("foo");

}

有一点需要注意:

因为C++ 程序调用xxx-xxx-g++编译,所以使用C++命名规范命名 符号,

这样,Java JNI程序就找不到对应符号了。

所以需要添加:

#ifdef __cplusplus

extern "C"{

#endif

function 声明。

#ifdef __cplusplus

}

#endif


3. 对std::wstring支持:

在NDK R7中,如果不做处理,则std::wstring会报未定义。

于是Sam查找之:

在:android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include/bits/stringfwd.h

#ifdef _GLIBCXX_USE_WCHAR_T

template<> struct char_traits;

typedef basic_string wstring;

#endif

所以,如果想要支持wstring,则需要定义 _GLIBCXX_USE_WCHAR_T

于是:在Android.mk中,

在LOCAL_CXXFLAGS,LOCAL_CFLAGS中添加:

-D_GLIBCXX_USE_WCHAR_T

即可支持wstring.

更新:Sam发现,wstring在R7C版本中,编译虽然没有问题,但链接时会报错。

只有替换了NDK R8之后,才真正没有问题了。

Android C++库支持有些不妥之处,例如:

在多Thread中使用cout,或者cout 与printf混和使用,会造成程序卡死。

注意:此处NDK版本为NDK R7C.(不同NDK版本,ndk-build所产生的Makefile并不完全相同)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: