How to redirect STDOUT to NSTextView?

Can someone show me how to redirect Stdout to NSTextView?

and is the NSLog info printout suitable for std?

thanks

+6
source share
2 answers

The code below uses dup2 to connect stdout to the end of an NSPipe object NSPipe . The end of reading is observed with the GCD sending source, which reads the data from the channel and adds it to the text box.

 NSPipe* pipe = [NSPipe pipe]; NSFileHandle* pipeReadHandle = [pipe fileHandleForReading]; dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stdout)); source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, [pipeReadHandle fileDescriptor], 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); dispatch_source_set_event_handler(source, ^{ void* data = malloc(4096); ssize_t readResult = 0; do { errno = 0; readResult = read([pipeReadHandle fileDescriptor], data, 4096); } while (readResult == -1 && errno == EINTR); if (readResult > 0) { //AppKit UI should only be updated from the main thread dispatch_async(dispatch_get_main_queue(),^{ NSString* stdOutString = [[NSString alloc] initWithBytesNoCopy:data length:readResult encoding:NSUTF8StringEncoding freeWhenDone:YES]; NSAttributedString* stdOutAttributedString = [[NSAttributedString alloc] initWithString:stdOutString]; [self.logView.textStorage appendAttributedString:stdOutAttributedString]; }); } else{free(data);} }); dispatch_resume(source); 

NSLog(@"...") not displayed on stdout , though - it prints before stderr . If you want to redirect this to your text view, change

 dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stdout)); 

to

 dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stderr)); 
+6
source

if the goal is to only process NSLog output and not system error logs, there is another way to do this, here is the code to redirect NSLog. This code only prints a log and additional information about stderr instead of the usual NSLog output, but you can make any changes that suit your needs inside the HyperLog function:

HyperLog.h

 #import <Foundation/Foundation.h> #ifdef HYPER_LOG #define NSLog(args...) HyperLog(__FILE__,__LINE__,__PRETTY_FUNCTION__,args); #else #define NSLog(x...) #endif void HyperLog(const char *file, int lineNumber, const char *functionName, NSString *format, ...); 

Hyperlog.m

 #import "HyperLog.h" void HyperLog(const char *file, int lineNumber, const char *functionName, NSString *format, ...) { va_list ap; va_start (ap, format); if (![format hasSuffix: @"\n"]) { format = [format stringByAppendingString: @"\n"]; } NSString *body = [[NSString alloc] initWithFormat:format arguments:ap]; va_end (ap); NSString *fileName = [[NSString stringWithUTF8String:file] lastPathComponent]; char mesg[8192]="\0"; NSDate *now =[NSDate date]; NSString *dateString = [NSDateFormatter localizedStringFromDate:now dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterMediumStyle]; if ( sprintf( mesg, "<%s.%03.0f> : %s\n<%s : %d - %s>\n", [dateString UTF8String],roundf(fmod( [now timeIntervalSinceReferenceDate], 1 ) * 1000), [body UTF8String], [fileName UTF8String], lineNumber, functionName) < 0 ) printf("message creation failed\n"); fprintf(stderr, "%s", mesg ); } 

You only need to put these 2 lines on top of any file in your program so that it works

 #define HYPER_LOG #import "HyperLog.h" 

I tried to use the above code from Thomas to get the result of a system error log written to a text file using the C function, which works correctly in other contexts, but it persists and the failure and the cause of the error is lost in the process. Does anyone have an idea why?

0
source

Source: https://habr.com/ru/post/944336/


All Articles