Is "std :: cout" usable on Android-ndk

In Android-ndk, we can use "__android_log_write", "__android_log_print", ... etc. to display messages in the "LogCat" window. How about if I use "std :: cout" to output some lines? For example.

std::cout << "some strings" << std::endl; 

Where the lines will be sent.

It seems that Android does not have console applications, and the above lines cannot be sent. Can I redirect "stdout" to a file so that sending strings to "std :: cout" is equivalent to logging messages?

+28
c ++ android-ndk console
Jan 15 '12 at 13:59
source share
4 answers

According to Android documentation, stdout and stderr are output to /dev/null . You can use Android Debug Bridge to achieve what you want.

By default, the Android system sends the stdout and stderr outputs (System.out and System.err) to / dev / null. In processes that run Dalvik VM, you can write a copy of the log file to the system. In this case, the system writes messages to the log using the log tags stdout and stderr, as with priority I. To route output in this way, you stop the emulator / device instance from starting, and then use the shell setprop command to enable output redirection. Here's how you do it:

 $ adb shell stop $ adb shell setprop log.redirect-stdio true $ adb shell start 

The system saves this parameter until you finish the emulator / device instance. To use the default option in the emulator / device instance, you can add an entry to /data/local.prop on the device.

+25
Jan 15 '12 at 14:11
source share

You can create a class derived from std::streambuf that uses special Android functions to send the generated character sequence. However, I don't know where, by default, the std::cout implementation sends characters to Android. Basically, it will look something like this:

 class androidbuf : public std::streambuf { public: enum { bufsize = 128 }; // ... or some other suitable buffer size androidbuf() { this->setp(buffer, buffer + bufsize - 1); } private: int overflow(int c) { if (c == traits_type::eof()) { *this->pptr() = traits_type::to_char_type(c); this->sbumpc(); } return this->sync()? traits_type::eof(): traits_type::not_eof(c); } int sync() { int rc = 0; if (this->pbase() != this->pptr()) { char writebuf[bufsize+1]; memcpy(writebuf, this->pbase(), this->pptr() - this->pbase()); writebuf[this->pptr() - this->pbase()] = '\0'; rc = __android_log_write(ANDROID_LOG_INFO, "std", writebuf) > 0; this->setp(buffer, buffer + bufsize - 1); } return rc; } char buffer[bufsize]; }; 

To actually configure std::cout to write to this stream buffer, you would do something similar in your main() function:

 int main() { std::cout.rdbuf(new androidbuf); ... } 

This creates a memory leak for a single androidbuf stream, which, however, is somewhat deliberate: the stream can be written after main() completed, and it is cleared when std::cout destroyed. If you do not want this, you can restore the original stream buffer std::cout or set it to null and remove the return from rdbuf() :

  // avoid a one-time resource leak but don't get output afterwards: delete std::cout.rdbuf(0); 
+27
Jan 15 '12 at 14:13
source share

Another option:

 #include <sstream> class MyStream { private: std::stringstream m_ss; int m_logLevel; public: MyStream(int Xi_logLevel) { m_logLevel = Xi_logLevel; }; ~MyStream() { __android_log_print(m_logLevel,LOG_TAG,"%s", m_ss.str().c_str()); } template<typename T> MyStream& operator<<(T const& Xi_val) { m_ss << Xi_val; return *this; } }; #define MY_LOG(LOG_LEVEL) MyStream(ANDROID_LOG_##LOG_LEVEL) << __FUNCTION__ << ":" << __LINE__ << " : " 

PROS:

(1) Messages are printed immediately.

MINUSES:

(1) You must change your code (std :: cout → MY_LOG (X)).

(2) Each individual seal creates an object and destroys it.

(*** This database of answers to this answer )

+2
Aug 04 '16 at 3:56 on
source share

Dietmar Kühl's answer is very good, but it does not work with boost.log from Crystax NDK . I found another idea and fixed it a bit. Here is the code:

 #include <iostream> #include <unistd.h> #include <pthread.h> #include <android/log.h> static int pfd[2]; static pthread_t thr; static const char *tag = "myapp"; static void *thread_func(void*) { ssize_t rdsz; char buf[128]; while((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) { if(buf[rdsz - 1] == '\n') --rdsz; buf[rdsz] = 0; /* add null-terminator */ __android_log_write(ANDROID_LOG_DEBUG, tag, buf); } return 0; } int start_logger(const char *app_name) { tag = app_name; /* make stdout line-buffered and stderr unbuffered */ setvbuf(stdout, 0, _IOLBF, 0); setvbuf(stderr, 0, _IONBF, 0); /* create the pipe and redirect stdout and stderr */ pipe(pfd); dup2(pfd[1], 1); dup2(pfd[1], 2); /* spawn the logging thread */ if(pthread_create(&thr, 0, thread_func, 0) == -1) return -1; pthread_detach(thr); return 0; } 

And its use:

 ... start_logger("MyApp"); ... 

Now all the output from boost.log to std :: cout and std :: cerr will be in logcat:

 #include <boost/log/utility/setup/console.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/sources/record_ostream.hpp> #include <boost/log/sources/logger.hpp> ... boost::log::add_console_log(std::cout); boost::log::add_common_attributes(); boost::log::sources::logger_mt lg; BOOST_LOG(lg) << "Hello, World!"; ... 
+1
Aug 02 '15 at 21:57
source share



All Articles