nlohmann / json

JSON for Modern C++
https://json.nlohmann.me
MIT License
43.22k stars 6.74k forks source link

Error compile Android NDK error: 'strtof' is not a member of 'std' #219

Closed fh127 closed 8 years ago

fh127 commented 8 years ago

hi, can you help me, this error occurs when it compile with Android NDK

          error: 'strtof' is not a member of 'std'
         return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);

         error: 'ERANGE' was not declared in this scope
         if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
Teemperor commented 8 years ago

For ERANGE see the PR. However, the std::strtof in the latest NDK STL looks fine to me and seems to be correctly used in this project. So I would say that there is a problem in your project setup (outdated NDK, weird defines, wrong STL?) and you rather find a solution in an Android developer forum :).

Also try to only run the preprocessor on the problematic source code and check if the included headers are actually defining strtof and are using them in the std namespace (e.g. by running GCC -E ...).

nlohmann commented 8 years ago

I merged PR #222. @fh127, is your issue solved by this?

vjjjv commented 8 years ago

I came across the same problem (in my project, changing or tweaking NDK settings was not an option because of other dependancies) and ended up fixing using a workaround. I hope there would be a cleaner solution though.. What I did:

For GCC 4.9 (for example ndk r10d):

Add to_string in the beginning of json.hpp

#include <vector>

#ifdef JSON_ANDROID_WORKAROUNDS
namespace std
{
    template < typename T > std::string to_string(const T& n)
    {
        std::ostringstream stm;
        stm << n;
        return stm.str();
    }
}
#endif

// disable float-equal warnings on GCC/clang

Use strtod in two places (warning! this will of course lose precision and maybe other errors):

        long double str_to_float_t(long double* /* type */, char** endptr) const
        {
#ifdef JSON_ANDROID_WORKAROUNDS
            return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
#else
            return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
#endif
        }
        float str_to_float_t(float* /* type */, char** endptr) const
        {
#ifdef JSON_ANDROID_WORKAROUNDS
            return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
#else
            return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
#endif
        }

For GCC 4.8 this was also needed (ndk r9c):

#ifdef JSON_ANDROID_WORKAROUNDS
    basic_json() {};
#else
    basic_json() = default;
#endif
fh127 commented 8 years ago

Hi, @nlohmann , I tested the commit PR #222, when I am compiling in Android NDK, this error was solved: error: 'ERANGE' was not declared in this scope''' But I have more errores: error: 'strtof' is not a member of 'std' error: 'strtoll' is not a member of 'std'

I am using the Android NDK configuration, and doesn't support those function c. Application.MK:

                APP_STL := gnustl_static
                APP_CPPFLAGS :=  -std=c++11 -frtti -fexceptions
                APP_ABI :=  armeabi armeabi-v7a x86 arm64-v8a
                 NDK_TOOLCHAIN_VERSION := 4.9

this commit of the repository #c0bb5a5 work fine for my Android project

Dimon4eg commented 8 years ago

I use CrystaX NDK and it compiles all fine for android.

nlohmann commented 8 years ago

@fh127 @Dimon4eg As the code works in your cases, could you please give me a detailed version number of your NDK/GCC so that I can mention it in the README file?

@vjjjv I don't want to add these adjustments to my code, because GCC 4.8 is not supported anyway.

Dimon4eg commented 8 years ago

Instead of Google NDK I use CrystaX NDK (latest 10.3.1 from https://www.crystax.net).

vjjjv commented 8 years ago

How about the GCC 4.9, I posted two workarounds for that too?

Its just a bit uncomfortable that a great lib is not compatible with some common dev envs because of such a small changes.. Or am I missing some bigger issues here? Is it so that it's not recommended to use the lib with changes that I made? (I am not super familiar with c++11 "specialities")

gregmarr commented 8 years ago

@vjjjv Can you not use the c++-shared standard library to get the missing to_string function?

vjjjv commented 8 years ago

I am not sure, because I experience this problem using Unity and Qt frameworks for example - there the NDK settings come predefined and its not very clear if I can change them easily.

nlohmann commented 8 years ago

Can someone please provide an example project so I can try to execute the build myself? (I have no experience with Android NDK - I just want to install it in an Ubuntu VM and try it myself.)

nlohmann commented 8 years ago

Ok, I tried the following: I got Android NDK, Revision 11c and compiled the unit tests with the following files in a subdirectory Android:

Android.mk:

LOCAL_PATH := .
include $(CLEAR_VARS)
LOCAL_MODULE := jsonunit.out
LOCAL_SRC_FILES := ../test/unit.cpp
LOCAL_C_INCLUDES += ../src ../test
LOCAL_CPP_FEATURES += exceptions rtti
LOCAL_CPPFLAGS += -fexceptions -frtti -std=c++11
include $(BUILD_EXECUTABLE)

Application.mk:

APP_ABI := x86
APP_PLATFORM := android-21
APP_STL := c++_shared
APP_BUILD_SCRIPT := Android.mk

Executing ndk-build NDK_APPLICATION_MK=./Application.mk takes a long time, but completes without error.

I have no experience with Android NDK. Can someone please tell me:

I really want to experience the reported problems on my machine to assess whether it makes sense to adjust the code. This may also be applicable to #136.

nlohmann commented 8 years ago

I had another try with the configuration above and only adjusted the NDK_TOOLCHAIN_VERSION parameter:

nlohmann commented 8 years ago

I forgot to mention: So far, I was not able to reproduce the 'to_string' is not a member of 'std' error.

nlohmann commented 8 years ago

I checked another NDK:

vjjjv commented 8 years ago

Thank you for investigating this! Can you try with this Application.mk:

APP_ABI := x86 APP_PLATFORM := android-21 APP_STL := gnustl_static APP_BUILD_SCRIPT := Android.mk

For me, this is how the issue re-produces. With "APP_STL := c++_shared" there is no issues, but as I mentioned before, in our project we cannot change the STL version.

nlohmann commented 8 years ago

Ok, I'll check this weekend. Which NDK version and compiler shall I try?

vjjjv commented 8 years ago

For us, r10d GCC 4.9 is relevant

nlohmann commented 8 years ago

I can reproduce the error.

Combinations that do not work:

Combinations that do work:

A longer explanation can be found here.

Is changing to one of the working combinations an option for you @vjjjv?

nlohmann commented 8 years ago

(I removed the bug label, because the error is out of scope of the library, but is a known issue for the combination of used options in Android NDK)

vjjjv commented 8 years ago

Interesting results on this one after all. We are using this json-lib in component that has to work with Unity and Qt frameworks - so it might be quite challenging to change the NDK options. But I could think Unity and Qt are also moving towards these better working setups in the long run.

For now we are quite happy with the workarounds I have posted here earlier. It seems that this should not be fixed in the json lib now when we know where the problem originates from.

nlohmann commented 8 years ago

I added a note to the README file and linked this discussion.

haydenkaizeta commented 7 years ago

Does anyone have this working for the most recent NDK while using gradle? I use

    ndk {
        stl "c++_static"
    }

    externalNativeBuild {
        cmake {
            cppFlags "-fexceptions -frtti -std=c++11"
        }
    }

and I still get the 'to_string' is not a member of 'std'

nlohmann commented 7 years ago

I could compile the code, see https://github.com/nlohmann/json/issues/451#issuecomment-281374011.

haydenkaizeta commented 7 years ago

I have no idea why but I needed this instead (this took me a few hours to figure out so hopefully it helps someone on Android using Gradle...):

    externalNativeBuild {
        cmake {
            cppFlags "-fexceptions -frtti -std=c++11"
            arguments "-DANDROID_STL=c++_shared"
        }
    }
nlohmann commented 7 years ago

@haydenkaizeta Thanks for sharing. Could you please give the exact version numbers so I can add a hint to the README?

haydenkaizeta commented 7 years ago

android-ndk-r13b, buildToolsVersion "24.0.3", ANDROID_STL=c++_shared, built with clang

fnc12 commented 7 years ago

For me compiles ok with CrystaX NDK (but I'm not using this lib as separate cmake module, just include as header)

iceflame89 commented 4 years ago

When using gnustl, add -D_GLIBCXX_USE_C99=1 -D_GLIBCXX_HAVE_WCSTOF=1 would fix it.
Tested with NDK r16b clang

More detail: to_string is not available in gnu-libstdc++ "out of the box". I searched the sources and found that std::to_string is indeed in the lib (${NDK_HOME}/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/basic_string.h) but opted out by

#if ((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
     && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))

see: https://stackoverflow.com/a/34352742/2395134

for armeabi-v7a , need -D_GLIBCXX_HAVE_WCSTOF=1 for std::wcstof