我正在从USB打印机进行异步读取。阅读工作正常。我的麻烦是从回调中更新NSTextField。
-(IBAction)printTest:(id)sender
{
// Setup... then:
NSLog(@"starting async read: %@", _printerOutput);
NSLog(@"_printerOutput pointer = %p", _printerOutput);
result = (*interface)->ReadPipeAsyncTO(interface,
1,
readBuffer,
numBytesRead,
500,
1000,
USBDeviceReadCompletionCallback,
&(_printerOutput)
);
回调定义为:
void USBDeviceReadCompletionCallback(void *refCon, IOReturn result, void *messageArg)
{
NSTextField *printerOutput = (__bridge NSTextField *) messageArg;
NSLog(@"_printerOutput pointer = %p", printerOutput);
}
指针在回调内部时会丢失其值。
starting async read: <NSTextField: 0x10221dc60>
_printerOutput pointer = 0x10221dc60
_printerOutput pointer = 0x0
我曾在许多地方试图模仿传递指针的不同方法。只有一种正确的方法。 :)
主题的另一个变体:(__ bridge void *)(_ printerOutput)。这也不起作用。
我知道回调的类型为IOAsyncCallback1。
其他注意事项: http://www.google.com/search?client=safari&rls=en&q=another+usb+notification+example&ie=UTF-8&oe=UTF-8和updating UI from a C function in a thread
答案 0 :(得分:0)
我认为_printerOutput
是NSTextField*
?
首先,为什么要将NSTextField**
传递给回调? (注意你传递给ReadPipeAsyncTO
的最后一个参数中的&符号。)
其次,我会使用敏感代码避免使用ARC,这只是一种预防措施。
第三,from what I see,ReadPipeAsyncTO
的最后一个参数称为refcon
。将回调的第一个参数称为refCon
是巧合吗?请注意,您尝试从messageArg
获取文本字段,而不是refCon
。
延伸我的第三点......
ReadPipeAsyncTO
有一个名为refcon
的参数。这是最后一个参数。_printerOutput
。不是指向_printerOutput
的指针(不通过&(_printerOutput)
) - _printerOutput
已经是指针。refcon
。事实上 - 让我们看看Apple docs对此回调的评价:REFCON
refcon传入原始I / O请求
我的结论是你的代码应该是:
void USBDeviceReadCompletionCallback(void *refCon, IOReturn result, void *messageArg)
{
NSTextField *printerOutput = (__bridge NSTextField *) refCon; // <=== the change is here
NSLog(@"_printerOutput pointer = %p", printerOutput);
}
请你试试这个吗?我觉得你没有尝试过这个。
小但可能很重要的题外话:是否是其他一些对象,如果你没有使用ARC,我建议在将_printerOutput
变量传递给ReadPipeAsyncTO
时将其保留,并将其释放回调。
但是,由于文本字段应该具有应用程序的生命周期,因此可能没有必要这样做。
ARC可能会失去对指针后面对象的需求的跟踪,一旦它被传递到C代码中,但它没关系,因为指针仍然存储在printerOutput
属性中。此外,一旦指针在C代码中,没有任何东西可以“跟随它”和“重置它”。
理解和解释概念时的困惑正是我说“避免使用敏感代码的ARC”的原因。 : - )