Writing NSString to a file descriptor

  • Hi,

    I am writing a wrapper class around a library written by one of my
    colleagues, and  I having troubles with writing an NSString to a file
    descriptor. The main function of the library takes a file descriptor
    as argument, and reads from that file descriptor. As my colleague
    cannot modify the library without changing a lot of things for a lot
    of people, I though I would create a NSFileHandle, get the associated
    file descriptor and pass it to the library function. Does it look like
    a good idea?

    Just to test this possible solution I wrote the following test code:

    - (void)useTool
    {
    NSString *msgStr = [[NSString alloc] initWithContentsOfFile:
    [[NSBundle mainBundle] pathForResource:@"test" ofType:@"spam"]];
    NSData *msgData = [msgStr dataUsingEncoding:NSASCIIStringEncoding];
    NSPipe *pipe = [NSPipe pipe];
    NSFileHandle *fh = [pipe fileHandleForWriting];

    [[NSNotificationCenter defaultCenter] addObserver:self
                            selector:@selector(getData:)
          name:NSFileHandleReadCompletionNotification
          object:fh];
    [fh readInBackgroundAndNotify];
    [fh writeData:msgData];
    }

    - (void)getData:(NSNotification*)note
    {
    NSFileHandle *fh = [note object];
    Tool *tool = [[Tool alloc] init];
    int res = 0;
    int fd = [fh fileDescriptor];

    res = [tool analyzeMessageFromFileDescriptor:fd];

    [spamc release];
    [fh release];
    }

    The problem is that it does not work... If I had:

    NSLog(@"%d",fd);
    NSLog(@"%@",[fh availableData]);

    I get a file descriptor, but the second NSLog returns:

    *** -[NSConcreteFileHandle availableData]: Bad file descriptor

    Can someone help me? Maybe using a NSFileHandle is not the best
    solution... but if you know another one, I would be glad to here it!

    Thanks a lot in advance,

      -- Arthur;

    --
    Arthur VIGAN
    AstroK Software
    <contact...>
  • Hi Arthur,

    > NSPipe *pipe = [NSPipe pipe]; // Allocation of
    autoreleased "pipe"

    > NSFileHandle *fh = [pipe fileHandleForWriting]; //
    since "pipe" is autoreleased "fh" is too.

    > [fh readInBackgroundAndNotify]; // you are reading in
    background, so your app will go through event loop.

    When your callback is called, your pipe is probably
    released and so your file handle is gone too, which
    results in bad file descriptor. Get pipe with [[NSPipe
    alloc] init] and release it when done with it.

    Regards,
    Gorazd

          Ask a question on any topic and get answers from real people. Go to Yahoo! Answers and share what you know at http://ca.answers.yahoo.com
  • Hi Gorazd,

    thanks for your answer. I tried allocating the pipe with [[NSPipe
    alloc] init], but I still get a "Bad file descriptor". I really don't
    get what is wrong. I also tried to retain the file handle fh, just in
    case, but it doesn't work either...

      -- Arthur;

    Le 20 nov. 07 à 21:52, Gorazd Krosl a écrit :

    > Hi Arthur,
    >
    >> NSPipe *pipe = [NSPipe pipe]; // Allocation of
    > autoreleased "pipe"
    >
    >> NSFileHandle *fh = [pipe fileHandleForWriting]; //
    > since "pipe" is autoreleased "fh" is too.
    >
    >> [fh readInBackgroundAndNotify]; // you are reading in
    > background, so your app will go through event loop.
    >
    > When your callback is called, your pipe is probably
    > released and so your file handle is gone too, which
    > results in bad file descriptor. Get pipe with [[NSPipe
    > alloc] init] and release it when done with it.
    >
    > Regards,
    > Gorazd
  • On 20 Nov 2007, at 18:47, AstroK Software wrote:

    > Just to test this possible solution I wrote the following test code:
    >
    > - (void)useTool
    > {
    > NSString *msgStr = [[NSString alloc] initWithContentsOfFile:
    > [[NSBundle mainBundle] pathForResource:@"test" ofType:@"spam"]];
    > NSData *msgData = [msgStr dataUsingEncoding:NSASCIIStringEncoding];
    > NSPipe *pipe = [NSPipe pipe];

    The first problem is that this pipe is autoreleased, as another poster
    pointed out

    > NSFileHandle *fh = [pipe fileHandleForWriting];

    The second problem is that here you have a file handle that is only
    good for *writing*...

    > [[NSNotificationCenter defaultCenter] addObserver:self
    > selector:@selector(getData:)
    > name:NSFileHandleReadCompletionNotification
    > object:fh];
    > [fh readInBackgroundAndNotify];

    ...and here you're trying to read from it.

    The file handles you get from NSPipe are unidirectional file handles,
    like the ones you get from the UNIX pipe() function.  It sounds to me
    like you're going to need a UNIX domain socket instead (sockets are
    bidirectional, so you can use the same file handle for reading and
    writing, though you'll still need one at each end).

    Consider using socketpair() to create a pair of connected, unnamed,
    UNIX domain sockets.  You can then use NSFileHandle or NS/CFStream as
    appropriate.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today