开发者

CFReadStreamSetClient Callback function - How do I give the C callback function a reference to the containing class?

I am assing a client callback function on a network read stream below:

 -(void)connectToServer
{
    if([self isServerConfigured])
    {
        CFReadStreamRef readStream; 
        CFWriteStreamRef writeStream;
        CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, (CFStringRef)self.serverAddress);
        CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, host, self.port, &readStream, &writeStream);

        CFStreamClientContext myContext = {
            0,
            self,
            (void *(*)(void *info))CFRetain,
            (void (*)(void *info))CFRelease,
            (CFStringRef (*)(void *info))CFCopyDescription
        };

        CFOptionFlags registeredEvents = kCFStreamEventHasBytesAvailable |
        kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;

        if(CFReadStreamSetClient(readStream, registeredEvents, serverCB, &myContext))
        {
            CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
        }
        if(!CFReadStreamOpen(readStream)){
            NSLog(@"Could not open read stream");
        }
    }
}

I would like this callback function to be able to call instance functions in the current object (self). It does not appear that CFReadStreamSetClient will allow me to change the callback functions signature and so I cannot just pass a reference to the current object to the callback I don't think.

This is the callback function:

 void serverCB(CFReadStreamRef stream, CFStreamEventType event, void *myPtr)
{
    switch(event) {
        case kCFStreamEventHasBytesAvailable:
            [self readStreamData:stream];
            break;
    开发者_Go百科    case kCFStreamEventErrorOccurred:
            NSLog(@"A Read Stream Error Has Occurred!");
            break;
        case kCFStreamEventEndEncountered:
            NSLog(@"A Read Stream Event End!");
            break;
        default:
            break;
    }
}

ServerCB will not know what 'self' is in this context. Can someone give me a pointer on how I can work around this?

Thanks!


myPtr == self in this case, as self is the value you gave your context's info field. That field is then passed to the callback by way of the last argument. So:

void serverCB(CFReadStreamRef stream, CFStreamEventType event, void *myPtr) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    {
        MyClass *self = [[(MyClass *)myPtr retain] autorelease];

        // ...
        // ...
        // ...

    }
    [pool drain];
}

(Because this is the Core Foundation level, there's no guarantee that an autorelease pool is in place, so it's common to see Objective-C in these callbacks wrapped in an autorelease pool, just in case.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜