1

I have quite a lot of debugging monitoring all over my program so whenever something undesired happens a message appears in XCode with "std::cout" showing what happended, where it happened, and so on. While I was testing the app on an iPhone or iPad connected to my computer, this worked as well (as I always had XCode open to show the fault).

But now I installed the app on devices of several beta-testers and they do not see these messages... Rewriting the code to route all the "cout" to a string would cost a lot of time as they appear everywhere in several classes and sub classes, etc...

is there a possibility of simply reading out the last line of the output console or detecting the event of writing to the console and then copying it over to a separate string?

  • There is no output console for apps that are run on a user's system. You're looking for [something like redirecting stdout to a stringstream](http://stackoverflow.com/questions/4810516/c-redirecting-stdout). Although I'd consider actually swapping from `std::cout` to something like [`NSLog`](https://developer.apple.com/library/ios/technotes/tn2347/_index.html). – Anya Shenanigans Mar 28 '16 at 16:45
  • NSLog is an objC command, I wrote my complete app in C++ with a slim wrapper above it to interface the display – Moritz Buchty Mar 28 '16 at 17:21
  • I was only commenting that logging with cout is poor practice. The linked question in my previous comment should allow you to redirect to a stringstream, which you can put on display, although, you may be better putting it into a file that your beta testers can forward on with a click of the 'send diagnostics email to developer' button – Anya Shenanigans Mar 28 '16 at 17:36
  • I think that "diagnostics email" sounds as a much better idea than what I had in mind... – Moritz Buchty Mar 28 '16 at 17:41

1 Answers1

0

This is something I've done on some android projects to forward stdout and stderr to logcat. You could use this same approach to forwards the stdout/stderr to anywhere you want:

struct stream {
   const char *name;
   int fd[2];
   FILE *src;
};

static void*
log_thread(void *arg)
{
   struct stream *stream = arg;
   char buf[4000], *off = buf, *nl; // Can't be too big or android stops logging
   for (ssize_t r = 0;;off += r, r = 0) {
      if (off - buf < sizeof(buf) - 1) {
         errno = 0;
         r = read(stream->fd[0], off, (sizeof(buf) - 1) - (off - buf));
         if (r <= 0) { if (errno == EINTR) continue; else break; }
         off[r] = 0;
      }
      if ((nl = strrchr(off, '\n'))) {
         *nl = 0; ++nl;
         __android_log_write(ANDROID_LOG_INFO, stream->name, buf);
         r = (off + r) - nl;
         memcpy((off = buf), nl, r);
      } else if (off - buf >= sizeof(buf)) {
         __android_log_write(ANDROID_LOG_INFO, stream->name, buf);
         r = 0; off = buf;
      }
   }
   close(stream->fd[0]);
   close(stream->fd[1]);
   return NULL;
}

__attribute__((constructor)) static void
log_init(void) {
   static struct stream stream[] = { { .name = "stdout" }, { .name = "stderr" } };
   stream[0].src = stdout; stream[1].src = stderr;
   for (size_t i = 0; i < sizeof(stream) / sizeof(stream[0]); ++i) {
      setvbuf(stream[i].src, NULL, _IOLBF, BUFSIZ);
      pipe(stream[i].fd);
      dup2(stream[i].fd[1], fileno(stream[i].src));
      pthread_t thread;
      pthread_create(&thread, 0, log_thread, &stream[i]);
      pthread_detach(thread);
   }
}