2013-05-06 12 views

答えて

6

以下のコードは、NSPipeオブジェクトの書き込み終了にSTDOUTをプラグインする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に出力します。あなたのTextViewにそれをリダイレクトしたい場合は、目標は、あなたのNSLog出力を処理する場合にのみ、システムはエラーログを生成しない、と他の方法がある

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

NSPipeがすでにバッファリングされている場合(独自の実装によって、またはラップされたOS構造体によってバッファされている場合)、独自のデータバッファを定義する必要があるのはなぜですか? – algal

+0

NSPipeはデフォルトではバッファリングされています( "パイプはバッファされていますが、バッファのサイズは基盤となるオペレーティングシステムによって決まります...")。しかし、チャンクを読み込み、自分のプロセス内でメモリ消費量をきめ細かく制御することは、依然として良い考えです。 (パイプのバッファのようなサウンドはOSによって維持されます) –

+0

また、 'do'ループは、それらの条件がないのではなくエラーまたは終了条件を誤ってテストしている可能性がありますか? – algal

0

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

を変更それでは、NSLogをオーバーライドするコードを示します。このコードは、代わりに通常のNSLog出力のログおよびstderrにいくつかの追加情報を印刷されていますが、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); 
} 

あなただけあなたのプログラムファイルのいずれかの上にこれらの2行を配置する必要があり はそれが仕事持っている

#define HYPER_LOG 
#import "HyperLog.h" 

私はトーマスから上記のコードを使用して、システム生成エラーログをC関数を使用してテキストファイルに書き出し、他のコンテキストでは正常に動作しますが、そのエラーは保持され、クラッシュします理由はプロセス中に失われます。誰でも理由が分かりますか?

関連する問題