2013-05-06 2 views

답변

6

코드는 아래 NSPipe 오브젝트의 추 단부에 표준 출력 플러그 dup2를 이용한다. 읽기 끝은 파이프에서 데이터를 읽어 텍스트 뷰에 추가하는 GCD 디스패치 소스에서 관찰됩니다.

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(@"...")하지만 stdout에 출력되지 않습니다 - 그것은 stderr에 인쇄합니다. 당신이 당신의 텍스트 뷰에 그 리디렉션하려면 목표 만 NSLog 출력이 아닌 시스템에서 생성되는 오류 로그를 처리하는 경우, 다른 방식이,

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

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

이것은 바보 같은 질문 일 수 있습니다 : NSPipe가 이미 버퍼링되었거나 (자체 구현에 의해 또는 다른 방법으로 랩핑 된 OS 구조에 의해) 버퍼링 된 경우 자체 데이터 버퍼를 정의해야하는 이유는 무엇입니까? – algal

+0

NSPipe가 기본적으로 버퍼링됩니다 ("파이프가 버퍼 됨, 버퍼의 크기는 기본 운영 체제에 의해 결정됩니다 ..."). 그러나 청크를 읽고, 자신의 프로세스 내에서 메모리 소비에 대해 세분화 된 제어를하는 것이 여전히 좋은 생각 일 수 있습니다. (파이프의 버퍼가 OS에 의해 유지되는 것처럼 들립니다.) –

+0

또한 'do' 루프가 이러한 조건이없는 오류나 종료 조건을 잘못 테스트 할 수 있습니까? – algal

0

변경 그렇다면 여기 NSLog를 오버 클래 싱하는 코드가 있습니다. 이 코드는 로그 대신 일반적인 NSLog 출력의 표준 오류에 대한 몇 가지 추가 정보를 인쇄하는,하지만 당신은의 HyperLOG의 함수 내에서 사용자의 요구 제품군 변경 할 수 있습니다 :

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

당신 만 프로그램 파일의 맨 위에 다음이 줄을 둘 필요가 가 작동해야합니다

#define HYPER_LOG 
#import "HyperLog.h" 

위의 코드를 토마스에서 사용하여 시스템의 결과 데이터를 생성하려고 시도했지만 오류 로그를 C 함수를 사용하여 텍스트 파일에 작성했습니다. 다른 문맥에서는 제대로 작동하지만 유지 및 충돌 및 오류 이유가 과정에서 없어집니다. 누구나 이유가 무엇입니까?

관련 문제