2012-01-15 13 views
29

En Android-ndk, podríamos usar "__android_log_write", "__android_log_print", ... etc para enviar mensajes a la ventana "LogCat". ¿Qué tal si uso "std :: cout" para producir algunas cadenas? P.ej.Es "std :: cout" utilizable en Android-ndk

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

Dónde se enviarán las cadenas.

Parece que Android no tiene aplicaciones de consola y las cadenas anteriores no se pueden enviar. ¿Podría redirigir el "stdout" a un archivo para que el envío de cadenas a "std :: cout" sea equivalente al registro de mensajes?

+0

subconjunto: redirigir la salida estándar a LogCat: http://stackoverflow.com/questions/10531050/redirect-stdout-to-logcat-in-android-ndk –

+0

duplicado posible de [C/C++ printfs - ¿Dónde aparece en un código nativo de Android?] (Https://stackoverflow.com/questions/6426911/cc-printfs-wheres-it-appears-in-a-android-native-code) –

Respuesta

25

De acuerdo con la documentación de Android, stdout & stderr salida a /dev/null. Puede usar el Android Debug Bridge para lograr lo que desea.

De forma predeterminada, el sistema Android envía salida stdout y stderr (System.out y System.err) a/dev/null. En los procesos que ejecutan la VM Dalvik, puede hacer que el sistema escriba una copia de la salida en el archivo de registro. En este caso, el sistema escribe los mensajes en el registro utilizando las etiquetas de registro stdout y stderr, ambos con prioridad I. Para enrutar la salida de esta manera, detiene una instancia de emulador/dispositivo en ejecución y luego utiliza el comando de shell setprop para habilitar la redirección de salida. He aquí cómo se hace:

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

El sistema conserva este ajuste hasta que termina la instancia de emulador/dispositivo. Para usar la configuración de manera predeterminada en la instancia del emulador/dispositivo, puede agregar una entrada a /data/local.prop en el dispositivo.

+0

Gracias, funciona – user1129812

+4

¿Funciona esto solo en dispositivos rooteados? – Ashwini

29

Puede crear una clase derivada de std::streambuf que utiliza las funciones específicas de Android para enviar la secuencia de caracteres producida. Sin embargo, no sé dónde la implementación predeterminada de std::cout envía caracteres a Android. Básicamente, esto sería algo como esto:

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]; 
}; 

Para establecer realmente para arriba std::cout escribir en este búfer de la secuencia, deberías hacer algo como esto en su función main():

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

Esto crear una memoria fugas para la secuencia androidbuf que, sin embargo, es algo intencional: la secuencia se puede escribir después de que main() se salga y se vacía cuando se destruye std::cout. Si no desea esto, se podía restaurar ya sea búfer de la secuencia original de std::cout 's o se establece en null y eliminar el regreso de rdbuf():

// avoid a one-time resource leak but don't get output afterwards: 
    delete std::cout.rdbuf(0); 
+0

Gracias por otra solución. Pero implica más codificación, lo intentaré más tarde. – user1129812

+2

Gracias, son trabajos. Pero tiene varios errores. Aquí está la versión fija: https://gist.github.com/dzhioev/6127982 – dzhioev

+0

¡Gracias! Modifiqué el código para que funcionara en realidad mediante copiar y pegar, espero que pueda ayudar a alguien. (podría estar pendiente la revisión por pares) –

1

La respuesta de Dietmar Kühl es muy buena, pero no lo hacen trabajar con boost.log desde Crystax NDK. Encontré another idea y lo he corregido un poco. Aquí está el código:

#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; 
} 

y su uso:

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

Ahora toda la salida de impulso.Registrar en std :: cout y std :: cerr estarán en 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!"; 
... 
2

Otra opción:

#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) Los mensajes se imprimen inmediatamente.

CONTRA:

(1) Usted debe cambiar su código (std :: cout -> MY_LOG (X)).

(2) Cada una sola impresión produce un objeto y lo destruye.

(*** This answer base on this answer)

Cuestiones relacionadas