• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: stdout redirect in xcode and not
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: stdout redirect in xcode and not


  • Subject: Re: stdout redirect in xcode and not
  • From: Aaron Burghardt <email@hidden>
  • Date: Fri, 02 Jan 2009 08:43:34 -0500

Hi Wesley,

If you disable caching on stdout/stderr, you shouldn't need to fflush() and poll. I am thinking of using this technique, too, so thanks for the idea. I created a test app to try it it, which is listed below. This example demonstrates a Cocoa implementation, but that isn't a requirement, though it does make it easy to deal with waiting for data. This sample also requires a NIB with an instance of AppController, an NSTextView and a NSButton. When the button is clicked, the stderr message is immediately added to the log text view. One nuisance with this sample is that NSLog() messages result in two instances of the message in the system log.

Aaron


AppController.h:

@interface AppController : NSObject
{
	IBOutlet NSTextView *logTextView;
	NSPipe *pipe;
}

- (IBAction)performTest:(id)sender;
@end


AppController.m:

#import "AppController.h"
#include <unistd.h>
#include <fcntl.h>

@implementation AppController

- (void)awakeFromNib
{
	pipe = [[NSPipe pipe] retain];
	NSFileHandle *readHandle = [pipe fileHandleForReading];
	NSFileHandle *writeHandle = [pipe fileHandleForWriting];

	fcntl([readHandle fileDescriptor], F_NOCACHE);
	fcntl([writeHandle fileDescriptor], F_NOCACHE);

	if (dup2([writeHandle fileDescriptor], STDERR_FILENO) == -1) {
		printf("failed to dup to stderr: (%i) %s\n", errno, strerror(errno));
		return;
	}

	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleStandardErrorNotification:)
												 name:NSFileHandleDataAvailableNotification
											   object:readHandle];
	[readHandle waitForDataInBackgroundAndNotify];
}

- (void)handleStandardErrorNotification:(NSNotification *)notif
{
NSData *data = [[notif object] availableData];
NSString *string = [[NSString alloc] initWithBytesNoCopy:(char *) [data bytes]
length:[data length]
encoding:NSUTF8StringEncoding
freeWhenDone:NO];

NSAttributedString *message = [[NSAttributedString alloc] initWithString:string];
[[logTextView textStorage] appendAttributedString:message];


	[string release];
	[message release];

	[[notif object] waitForDataInBackgroundAndNotify];
}

- (IBAction)performTest:(id)sender
{
fprintf(stderr, "Current time: %s\n", [[[NSDate date] description] UTF8String]);
}



On Dec 24, 2008, at 1:42 AM, Wesley Smith wrote:

Just to follow up, especially since it's hard to find precise info on
this subject on the interwebs.  The problem I was trying to solve was
how to direct stdout and stderr to an arbitrary memory buffer inside
an application.  In my case, I'm directing to to a console window and
a log file.

In the end, I had to use a polling method as I couldn't find any way
to get callbacks when a pipe has data to read off the read endpoint.

The setup looks like this:

FILE *readStream;
int spipe[2];

if(pipe(spipe) != 0) {
   // error
}

for(int n=0; n < 2; n++) {
   int f = fcntl(spipe[n], F_GETFL, 0);
   f |= O_NONBLOCK;
   fcntl(spipe[n], F_SETFL, f);
}

readStream = fdopen(spipe[0], "r");
dup2(spipe[1], fileno(stdout));

Then, you have to poll the readStrem FILE structure as follows:


std::string str; int res = 0; fflush(stdout); do { char buffer[128]; res = fread(buffer, 1, 127, readStream); buffer[res] = '\0'; str.append(buffer); } while(res > 0);


Obviously, the method of collecting chunks of data from the FILE can differ, but it is essential yo call fflush on stdout (or stderr as the case may be). I've found that not calling fflush results in nothing being read by fread.

wes
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

_______________________________________________ Do not post admin requests to the list. They will be ignored. Xcode-users mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Prev by Date: XCode's 2K9 bug??
  • Next by Date: Re: Interface Builder and NSView isFlipped
  • Previous by thread: XCode's 2K9 bug??
  • Next by thread: Re: Interface Builder and NSView isFlipped
  • Index(es):
    • Date
    • Thread