2008-11-25 87 views
5

我在Objective-C类中有一个方法。它具有用C编写的2个回调函数。类指针,即self作为void *传递给这些函数。在C函数中,我创建了一个类型指针并分配了参数void *。 第一个回调函数成功执行。但在第二个回调函数中void *指针变为nil。请注意,我在第一次回调中没有调整指针,但仍然在第二次回调中获得nil处理回调

任何想法可能会出错?

例如:

kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, 
             matchingDict, RawDeviceAdded, NULL, 
             &gRawAddedIter); 

RawDeviceAdded(NULL, gRawAddedIter, self); 

这工作得很好。但以下功能收到selfnil

kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, 
             matchingDict, BulkTestDeviceAdded, NULL, 
             &gBulkTestAddedIter); 

BulkTestDeviceAdded(NULL, gBulkTestAddedIter, self); 
+0

这将是更容易帮助,如果你可以编辑添加代码,显示你正在试图做什么。 – 2008-11-25 10:17:18

回答

1

通常,Objective-C中的回调是通过传递委托对象和选择器来处理该委托来处理的。例如,此方法在记录消息后将在其委托上调用一个方法,同时传递它自己和记录的消息。

- (void)logMessage:(NSString *)message 
      delegate:(id)delegate 
    didLogSelector:(SEL)didLogSelector 
{ 
    NSLog(@"%@", message); 

    if (delegate && didLogSelector && [delegate respondsToSelector:didLogSelector]) { 
     (void) [delegate performSelector:didLogSelector 
           withObject:self 
           withObject:message]; 
    } 
} 

你可以调用它的代码是这样的:

- (void)sayHello 
{ 
    [logger logMessage:@"Hello, world" 
       delegate:self 
     didLogSelector:@selector(messageLogger:didLogMessage:)]; 
} 

- (void)messageLogger:(id)logger 
     didLogMessage:(NSString *)message 
{ 
    NSLog(@"Message logger %@ logged message '%@'", logger, message); 
} 

您还可以使用objc_msgSend(),而不是直接,但你需要了解的Objective-C运行足够的选择使用哪一个变量,以及如何来构建通过它来调用它的原型和函数指针。 (这是消息发送实际在Objective-C中执行的机制 - 编译器通常会生成呼叫以代表[]表达式。)

+0

对不起 - 在发布代码之前,我想过的问题是如何编写在Objective-C中实现回调系统的代码,而不是使用C回调。 – 2008-11-25 22:33:41

10

是否您的问题专门用于IOKit回调例程?你给出的具体例子的问题是,IOServiceMatchingCallback只有2个参数,而不是3个。你需要你的RawDeviceAdded()和BulkTestDeviceAdded()回调函数来匹配IOServiceMatchingCallback原型,并接受self作为第一个参数(refCon),而不是第三。此外,您需要传入自身作为IOServiceAddMatchingNotification()的倒数第二个参数,以便通过回调传回给您。

在Objective-C代码中处理C回调的常见方法是使用静态函数将回调转发给您的实例。所以,你的例子回调代码应该是这样的:

static RawDeviceAdded(void* refcon, io_iterator_t iterator) 
{ 
    [(MyClass*)refcon rawDeviceAdded:iterator]; 
} 

@implementation MyClass 
- (void)setupCallbacks 
{ 
    // ... all preceding setup snipped 
    kr = IOServiceAddMatchingNotification(gNotifyPort,kIOFirstMatchNotification, matchingDict,RawDeviceAdded,(void*)self,&gRawAddedIter); 
    // call the callback method once to 'arm' the iterator 
    [self rawDeviceAdded:gRawAddedIterator]; 
} 
- (void)rawDeviceAdded:(io_iterator_t)iterator 
{ 
    // take care of the iterator here, making sure to complete iteration to re-arm it 
} 
@end