2012-01-15 10 views
29

एंड्रॉइड-एनएनडी में उपयोग करने योग्य "std :: cout" है, हम "logCat" विंडो में संदेशों को आउटपुट करने के लिए "__android_log_write", "__android_log_print", ... आदि का उपयोग कर सकते हैं। अगर मैं कुछ तारों को आउटपुट करने के लिए "std :: cout" का उपयोग करता हूं तो कैसे? जैसेएंड्रॉइड-एनएनडी

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

स्ट्रिंग कहां भेजे जाएंगे।

ऐसा लगता है कि एंड्रॉइड में कंसोल अनुप्रयोग नहीं हैं और उपर्युक्त तार नहीं भेजे जा सकते हैं। क्या मैं "stdout" को एक फ़ाइल में रीडायरेक्ट कर सकता हूं ताकि "std :: cout" पर स्ट्रिंग भेजना लॉगिंग संदेशों के बराबर है?

+0

सबसेट: stdout अनुप्रेषित Logcat रहे हैं: http://stackoverflow.com/questions/10531050/redirect-stdout-to-logcat-in-android-ndk की –

+0

संभावित डुप्लिकेट [सी/सी ++ printfs - यह एंड्रॉइड मूल कोड में कहां दिखाई देता है?] (Https://stackoverflow.com/questions/6426911/cc-printfs-wheres-it-appears-in-a-android-native-code) –

उत्तर

25

एंड्रॉइड प्रलेखन के अनुसार, stdout & stderr आउटपुट /dev/null पर। आप जो चाहते हैं उसे प्राप्त करने के लिए आप Android Debug Bridge का उपयोग कर सकते हैं।

डिफ़ॉल्ट रूप से, एंड्रॉइड सिस्टम stdout और stderr (System.out और System.err) आउटपुट को/dev/null भेजता है। दल्विक वीएम चलाने वाली प्रक्रियाओं में, आप सिस्टम को आउटपुट की प्रतिलिपि लॉग फ़ाइल में लिख सकते हैं। इस मामले में, सिस्टम लॉग टैग stdout और stderr का उपयोग कर लॉग को संदेश लिखता है, दोनों प्राथमिकता I. इस तरह से आउटपुट को रूट करने के लिए, आप एक चल रहे एमुलेटर/डिवाइस इंस्टेंस को रोकते हैं और फिर खोल कमांड setprop का उपयोग करते हैं आउटपुट के पुनर्निर्देशन को सक्षम करें। यहाँ कैसे आप यह कर दिया गया है:

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

प्रणाली इस सेटिंग को जब तक आप एमुलेटर/डिवाइस उदाहरण समाप्त बरकरार रखती है। एमुलेटर/डिवाइस इंस्टेंस पर डिफॉल्ट के रूप में सेटिंग का उपयोग करने के लिए, आप डिवाइस पर /data/local.prop में एक एंट्री जोड़ सकते हैं।

+0

धन्यवाद, यह काम करता है। – user1129812

+4

क्या यह केवल रूट डिवाइस पर काम करता है? – Ashwini

29

आप std::streambuf से प्राप्त कक्षा बना सकते हैं जो वर्णों के उत्पादित अनुक्रम को भेजने के लिए एंड्रॉइड विशिष्ट कार्यों का उपयोग करता है। मुझे नहीं पता कि std::cout का डिफ़ॉल्ट कार्यान्वयन एंड्रॉइड पर वर्ण भेजता है, हालांकि।

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

वास्तव में std::cout सेट करने के लिए इस धारा बफर करने के लिए लिखने के लिए, आप अपने main() समारोह में कुछ इस तरह करना होगा::

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

यह एक स्मृति बनाने मूलतः, यह कुछ इस तरह दिखेगा एक androidbuf धारा के लिए रिसाव, हालांकि, कुछ हद तक जानबूझकर है: main() के बाद स्ट्रीम को लिखा जा सकता है और जब std::cout नष्ट हो जाता है तो यह फ़्लश हो जाता है। आप इस नहीं करना चाहते हैं, आप या तो std::cout की मूल धारा बफर बहाल करने या इसे सेट शून्य पर और rdbuf() से वापसी हटा सकता है:

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

एक और समाधान के लिए धन्यवाद। लेकिन इसमें अधिक कोडिंग शामिल है, मैं इसे बाद में कोशिश करूंगा। – user1129812

+2

धन्यवाद, यह काम करता है। लेकिन इसमें कई गलतियां हैं। यहां निश्चित संस्करण है: https://gist.github.com/dzhioev/6127982 – dzhioev

+0

धन्यवाद! मैंने कॉपी और पेस्ट द्वारा वास्तव में काम करने के लिए कोड को संशोधित किया है, उम्मीद है कि यह किसी की मदद कर सकता है। (पीयर समीक्षा लंबित हो सकती है) –

1

डिटमार Kühl का जवाब बहुत अच्छा है, लेकिन यह नहीं है Crystax NDK से boost.log के साथ काम करें। मुझे another idea मिला और इसे थोड़ा सा सही किया है। यहाँ कोड है:

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

और इसके उपयोग:

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

अब सभी को बढ़ावा देने से उत्पादन।एसटीडी लॉग इन करें :: अदालत और std :: cerr 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

एक अन्य विकल्प:

#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__ << " : " 

पेशेवरों:

(1) संदेशों तुरंत मुद्रित कर रहे हैं।

कान्स:

(1) आप अपने कोड को बदलने के लिए चाहिए (std :: अदालत -> MY_LOG (एक्स))।

(2) प्रत्येक एकल प्रिंट एक वस्तु उत्पन्न करता है और इसे नष्ट कर देता है।

(*** This answer base on this answer)