安卓NDK是否支持std::to_string函数

48

我正在使用 Android NDK r9d 和 Toolchain 4.8,但我无法使用 std::to_string 函数,编译器会报错:

 error: 'to_string' is not a member of 'std'

这个函数在Android NDK上不受支持吗?我尝试使用APP_CPPFLAGS := -std=c++11,但是没有成功。

6个回答

62
你可以尝试使用LOCAL_CFLAGS := -std=c++11,但请注意,NDK的gnustl不支持所有的C++11 API。带有完整C++14支持的选项是libc++ (APP_STL := c++_shared)。

另一种选择是自己实现。

#include <string>
#include <sstream>

template <typename T>
std::string to_string(T value)
{
    std::ostringstream os ;
    os << value ;
    return os.str() ;
}

int main()
{
    std::string perfect = to_string(5) ;
}

3
我尝试了一些方法,但都没有成功(例如LOCAL_CPPFLAGS += -std=c++11,LOCAL_CPPFLAGS += -std=gnu+11等),我也找到了一些答案(https://dev59.com/7mMl5IYBdhLWcg3w_rOD#18124627)。这些答案解释了ndk不支持新的c++11字符串函数,所以最后我按照你的建议实现了to_string方法。谢谢 :)。 - albciff
我已经尝试过了,但在std::ostringstream上出现了错误。问题可能与Android Studio 2.2 alpha 6有关。有没有简单的方法可以转换? - Onur Tuna
非常有用,适用于不支持C++11的编译器。顺便问一下:是否有一种方法(宏定义)可以检查是否存在C++11,以便跳过此步骤? - Wolf
我刚刚发现 char 模板特化缺失,你需要为 char、signed char 和 unsigned char 分别提供 3 个。 - Wolf
我使用了相同的函数,但是应用程序在某些设备上崩溃,并显示以下日志 libloglib-jni.so 0xdd7bdacf std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_ostringstream() (basic_ios.h:276) 36 libart.so 0xf4832812 (缺失) 37 libloglib-jni.so 0xdd7a5851 std::string patch::to_string<int>(int const&) 如果您有任何解决方案,请提供。 - Om Infowave Developers
显示剩余2条评论

26

使用 NDK r9+,您可以使用llvm-libc++,它完全支持 cpp11。

在您的Application.mk中,您需要添加:

APP_STL:=c++_static 
或者
APP_STL:=c++_shared

2
使用cocos2d-x,这个方法可以解决std::to_string编译问题。但是它会导致其他构建问题:“错误:'pthread_key_t'未命名为类型static pthread_key_t s_threadKey”。如果有人尝试这个方法,我从来没有能够解决这个问题。正如在这里提到的http://stackoverflow.com/questions/22164564/cannot-build-local-shared-library-in-android-ndk更改编译器会导致其他编译问题... 接受的答案可以在短期内解决这个问题... - Hunter-Orionnoir
1
@Hunter,我在我的问题中没有提到这一点,但我正在使用cocos2d,而且被接受的答案非常干净,正如你所说,解决了这个问题,这就是为什么我接受它的原因 :) - albciff
是的,我也选择了被接受的答案,我无法确切地弄清楚如何正确使用这种方法。我缺少其他线程库。如果我花更多时间可能就能做到...我只是想在这里放置特定的错误,以便如果我再次遇到这个问题,我就可以立即解决 :) - Hunter-Orionnoir
我找了好几个小时,所以非常感谢thursdaysDove! - Kyone
我也会在这个答案的下游遇到其他错误。 - Jonny
显示剩余2条评论

13

Gradle

如果您正在寻找 Gradle 构建系统的解决方案,请查看这个答案

简短回答。

添加字符串:

arguments "-DANDROID_STL=c++_shared"

在你的 build.gradle 文件中。例如:

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {
        ...
        arguments "-DANDROID_STL=c++_shared"
      }
    }
  }
  ...
}

1
实际上,这是唯一有效的答案,因为今天的Android本地开发大多使用使用Gradle的Android Studio完成。 - Michael IV

1

实验性 Gradle 插件

如果您正在寻找实验性 Gradle 插件的解决方案,这个方法对我有效...

已测试通过 com.android.tools.build:gradle-experimental:0.9.1

model {
  ...
  android {
    ...
    ndk {
      ...
      stl = "c++_shared"
    }
  }
}

0

我无法使用c++_static,它会出现一些未定义异常的错误。所以我回到了gnustl_static

但是在NDK源代码中,在sources/cxx-stl/llvm-libc++/src/string.cpp中,我找到了to_string(int)的实现,并尝试将其复制到我的代码中。经过一些更正后,它可以工作了。

所以我最终得到的代码片段是:

#include <string>
#include <algorithm>

using namespace std;


template<typename S, typename P, typename V >
inline
S
as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
{
    typedef typename S::size_type size_type;
    size_type available = s.size();
    while (true)
    {
        int status = sprintf_like(&s[0], available + 1, fmt, a);
        if ( status >= 0 )
        {
            size_type used = static_cast<size_type>(status);
            if ( used <= available )
            {
                s.resize( used );
                break;
            }
            available = used; // Assume this is advice of how much space we need.
        }
        else
            available = available * 2 + 1;
        s.resize(available);
    }
    return s;
}

template <class S, class V, bool = is_floating_point<V>::value>
struct initial_string;

template <class V, bool b>
struct initial_string<string, V, b>
{
    string
    operator()() const
    {
        string s;
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, false>
{
    wstring
    operator()() const
    {
        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
          + 1;
        wstring s(n, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, true>
{
    wstring
    operator()() const
    {
        wstring s(20, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

string to_string(int val)
{
    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
}

0

对于 Android Studio,在 build.gradle(移动应用程序)中添加以下内容:

externalNativeBuild {
    cmake {
        cppFlags "-std=c++11"

        arguments "-DANDROID_STL=c++_static"
    }
}

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