Android源码中c++ STL的namespace

田海立@CSDN 2020-11-22

Android源码中的c++ STL》中讲到Android Source中有内置的LLVM c++ STL和NDK的c++ STL,使用到这两个stl的时候如何区分呢?c++是用namespace隔离的,stl也是这样隔离的。本文逐步分析STL中如何用namespace隔离这两个STL,这也同时可以解惑stl使用者使用时找不到stl中的标号的问题的原因。

应用使用stl,首先要有STL的原型,这些在各个stl的头文件里;而源文件被编译成库(动态.so/静态.a)。头文件与对应的库应该匹配使用。

1. STL c++头文件和源文件

Android中根据选择的stl会有不同的路径:
ndk:  prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/include/
aosp: external/libcxx/include/

STL中的头文件和源文件前后都会用下面的宏来包含:

_LIBCPP_BEGIN_NAMESPACE_STD
// sources or headers
_LIBCPP_END_NAMESPACE_STD

_LIBCPP_BEGIN_NAMESPACE_STD和_LIBCPP_END_NAMESPACE_STD定义在文件__config中,这些不同的STL路径下都会包含各自的__config文件。

2. _LIBCPP_BEGIN_NAMESPACE_STD和_LIBCPP_END_NAMESPACE_STD的定义【__config中】

_LIBCPP_BEGIN_NAMESPACE_STD和_LIBCPP_END_NAMESPACE_STD定义在文件__config

#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE {
#define _LIBCPP_END_NAMESPACE_STD  } }

2.1 _LIBCPP_NAMESPACE的定义

//__config: [external/libcxx/include/]
#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)

//__config: [prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/include/]
#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__ndk,_LIBCPP_ABI_VERSION)

2.1.1 _LIBCPP_CONCAT

#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
#define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)

2.1.2 _LIBCPP_ABI_VERSION

#ifndef _LIBCPP_ABI_VERSION
#define _LIBCPP_ABI_VERSION 1
#endif

所以,在Android源码中_LIBCPP_NAMESPACE有两个定义:
  - in libc++.so: __1
  - in libc++_shared: __ndk1
  
_LIBCPP_BEGIN_NAMESPACE_STD也就有两个定义:
  - in libc++.so: namespace std {inline namespace __1 {
  - in libc++_shared.so:  namespace std {inline namespace __ndk1 {

3. 结论

Android源码中的STLs:
namespace in libc++【头文件:  external/libcxx/include/】:
  std::__1
namespace in libc++_shared【头文件:  prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/include/】:
  std::__ndk1

所以,在编译链接时出现找不到STL中的变量/函数等错误(特别出现了namespace “std::__1”,“std::__ndk1”等字眼),要考虑使用STL的头文件路径/链接库等原因了。这会在诸如你的不同编译单元之前是单独编译的,而它们使用了的不一致的STL时出现。而如果使用到第三方库,需要与他们沟通使用一致的STL,不然等到运行时再出现莫名其妙的问题调试起来就更麻烦了。

猜你喜欢

转载自blog.csdn.net/thl789/article/details/109920740