fpagliughi / sockpp

Modern C++ socket library.
BSD 3-Clause "New" or "Revised" License
769 stars 126 forks source link

android build error: sockpp exception - no matching conversion for functional-style cast #52

Closed bmahlbrand closed 1 year ago

bmahlbrand commented 3 years ago

When building for Android targets, I've encountered the following error:

/workspace/myproject/third-party/sockpp/src/exception.cpp:70:15: error: no matching conversion for functional-style cast from 'int' to 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
                        return s ? std::string(s) : std::string();

I'll look into an actual resolution and submit a PR if the fix isn't immediately obvious, but was able to get around it by commenting it out, and the rest of the library built fine.

fpagliughi commented 3 years ago

A quick Google brings up what appears to be the problem, and a possible solution: https://stackoverflow.com/questions/32629222/how-to-use-strerror-r-properly-for-android

The conditional compilation for that line looks for GNU-specific behavior via _GNU_SOURCE . Android appears to have the macro defined even though it's not using the GNU behavior for strerror_r(). It appears to use the standard XSI-compliant behavior, returning an int instead of a char*.

The Linux man page claims:

The XSI-compliant version of strerror_r() is provided if: (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE Otherwise, the GNU-specific version is provided.

The Stack Overflow answer recommends (with zero votes):

#if !defined(__GLIBC__)
// use the XSI standard behavior.
#else
// assume GNU exception
#endif

So, we could try to make the conditional compilation more specific, or look for a completely different solution that is more portable.

Can you try some of this out and submit a PR if you get something that works? I don't have an Android development platform to test this.

bmahlbrand commented 3 years ago
        #ifdef _GNU_SOURCE
            #if !defined(__GLIBC__)
            // use the XSI standard behavior.
                int e = strerror_r(err, buf, sizeof(buf));
                auto s = strerror(e);
                return s ? std::string(s) : std::string();
            #else
            // assume GNU exception
                auto s = strerror_r(err, buf, sizeof(buf));
                return s ? std::string(s) : std::string();
            #endif
        #else
            ignore_result(strerror_r(err, buf, sizeof(buf)));
        #endif

Seems to be on the right track, I'll do some more testing to check that it actually behaves as expected and submit a PR.