如何在Android NDK和STLport中使用boost库(包括shared_ptr)

58

这更像是一个答案而不是一个问题,因为我已经找出来了,至少可以干净地编译库。对我来说,主要的问题是让shared_ptr正常工作。

材料:

Boost v. 1.45.0

STLport版本在http://www.anddev.org/viewtopic.php?p=29939上获取。

NDK的版本为r4b。

步骤:

在您的Android.mk文件中添加:

LOCAL_CFLAGS += -DBOOST_EXCEPTION_DISABLE -D_STLP_NO_EXCEPTIONS -DOS_ANDROID -D_STLP_USE_SIMPLE_NODE_ALLOC

请删除 stlport/stl/_string.h 文件中第 613 行中的 __stl_throw_length_error 调用。如果需要可以使用 _STLP_NO_EXCEPTIONS。

在 boost/boost/smart_ptr/shared_ptr.hpp 的第 261 行后进行编辑,以消除 shared_ptr 构造函数中对 boost::throw_exception 的调用。我使用了 #ifndef BOOST_EXCEPTION_DISABLE 来包含整个方法体。(但请参见下面的答案。)

接下来,您需要提供一些缺失的部分。创建一个具有以下内容的头文件:

#ifdef OS_ANDROID

#include <exception>

namespace std
{
    struct bad_alloc : public exception { bad_alloc operator()(){}};
}

#endif

还有一个源文件,其中包含一个简化的异常类来支持bad_alloc:

#ifdef OS_ANDROID

#include <exception>

namespace std
{
    exception::exception() {}
    exception::~exception() {}
    const char* exception::what() const {}
}

#endif

在包含boost/shared_ptr.hpp的任何位置都要包含这个头文件。编译源代码并将其添加到您的库中。


9
为了避免这个问题永远开着,如果您能按照FAQ的建议将此帖子重新表述为一个问题然后自己回答,那将非常酷。 - dennycrane
1
感谢分享你所学到的内容!我相信这对许多人都有帮助。 - Daniel Lidström
Dennycrane,我仍在尝试这种方法,所以我想保持开放,以防还有更多需要添加的内容。当我得到一个干净运行的库时,我会报告并用答案关闭问题。 - Gamma Draconis
1
我赞同@dennycrane提出的未来改进的建议,但更重要的是你花时间以任何格式在SO上发布了这个有用的指南。我已经发现它很有帮助,尽管我还没有阅读它;仅仅知道这是可能的将大大帮助我设计当前的项目。谢谢你为我和许多其他人节省了找到答案的时间,而无需提示问题。 - Daniel H
4个回答

39

事实证明,当编译可调试库时,这种方法并不能完全起作用。发布库是使用-O2编译的,它会优化掉一些不良因素,但是调试库使用-O0编译,会显露出一些额外的问题。此外,我对编辑boost文件也不太满意。因此,在进一步研究后,我提出了以下解决方案。

首先,不要编辑任何boost文件。而是在std命名空间内的头文件中添加以下内容:

struct bad_cast : public exception {bad_cast operator()(){}};

接下来将以下内容添加到源文件中:

namespace boost
{
    void throw_exception(std::exception const&) {}
}

现在即使在AndroidManifest.xml中包含android:debuggable="true",该代码也可以编译和链接到应用程序中。虽然在模拟器中无法运行,但在使用该库之前也是如此。


2
我尽可能地给了你赞。花了大约一整天的时间来弄清楚这个问题,找到这个解决方法非常有帮助。 - user562566
1
既然您已经像上面建议的那样回答了自己的问题,您应该得到另一个赞。我希望更多的人(包括不幸的是我自己)能够想到在这里发布他们辛苦找到的解决方案,而不需要别人要求。 - Daniel H

3
值得注意的是,NDK r5附带了STLport和GNU STL,因此现在不再需要这里的hack了,因为a)有STL支持b)NDK C ++编译器中有异常支持。

你的观点a和b在个别情况下是正确的,但在组合起来时却不是(请参见nkd文档中CPLUSPLUS-SUPPORT.html第III节中的WARNING)。因此,你仍然需要我所讨论的std::bad_alloc、std::bad_cast和boost::throw_exception的hack方法。 - Gamma Draconis
很奇怪。我引用的文档根本没有提到GNU STL,除了说“完全支持GNU libstdc++”是未来的计划。但是在NDK中却有它,位于sources/cxx-stl下面,还有他们的最小系统和stlport。你成功让它工作了吗?我注意到这个问题正在http://groups.google.com/group/android-ndk/browse_thread/thread/da175a5d6b8b7956上进行讨论。 - Gamma Draconis
似乎在NDK页面http://developer.android.com/sdk/ndk/index.html上提到了,而不是在文档中。引用“提供一个默认的C++ STL实现(基于STLport)作为帮助模块。它可以被用作静态或共享库(详细信息和使用示例在sources/android/stlport/README中)。STLport(静态或共享)和GNU libstdc++(仅静态)的预构建二进制文件。”看起来libstdc++与异常和RTTI一起工作。 - grrussel
我可以使用它进行编译,但是库链接阶段出现了许多未定义引用错误。我尝试了显式的LOCAL_LDLIBS += -lstdc++,但没有帮助。你已经成功使用APP_STL := gnustl_static了吗? - Gamma Draconis
是的,它对我来说可行。我不需要为STL添加显式的ld参数;对于我构建和使用的所有其他库都需要,但不包括STL本身。您可以使用std :: vector或类似内容的hello world进行验证。 - grrussel

1

对于shared_ptr,另一个解决方法是使用boost::intrusive_ptr。虽然这并非总是可行的,但在我的情况下起到了作用。


1
你也可以很容易地从shared_ptr_nmt.hpp中提取出简化版本的shared_ptr。 - Chris

1

当前版本的Android NDK(r9)现在支持异常。

各种运行时的功能有所不同。请参阅此表格:

          C++       C++   Standard
          Exceptions  RTTI  Library
system    no           no        no
gabi++   yes          yes        no
stlport  yes          yes       yes
gnustl   yes          yes       yes

stlport可以在非GPL二进制文件中使用。它仍被标记为实验性,但您可以在clang和gcc中使用它。

请参见http://developer.android.com/tools/sdk/ndk/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接