Пример кода для Mac с использованием USB и CFRunLoopSource

Я пытаюсь (пере) написать программу, которая использует сканеры, управляемые через USB. У меня настроен USBIOInterfaceInterface, так что я могу отправлять и получать сообщения по каналам. Я успешно вызываю WritePipeTO и ReadPipeTO синхронно, но я хочу читать со сканера асинхронно.

Я пытался использовать ReadPipeAsyncTO, но обратный вызов никогда не вызывается до истечения времени ожидания вызова. Причина, по-видимому, в том, что я где-то не регистрирую обратный вызов. Если я добавлю CFRunLoopRun после асинхронного чтения, то он, похоже, будет работать, но только за счет множества вложенных вызовов CFRunLoopRun, что не может быть хорошей идеей.

Я видел функции:

    err = (*usbInterfaceInterface)->CreateInterfaceAsyncEventSource(usbInterfaceInterface, &cfSource);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);

но я не понял, как сообщить источнику, какой обратный вызов следует вызывать, когда что-то происходит на этом интерфейсе. Когда я просто создаю источник и вызываю ReadPipeAsyncTO, обратный вызов не вызывается до истечения времени ожидания.

Есть ли где-нибудь такой же пример кода, чтобы я мог видеть, как эти функции ДОЛЖНЫ работать вместе?


person Brian Postow    schedule 25.07.2010    source источник


Ответы (1)


Вызов CFRunLoopRun или его эквивалента NSRunLoop почти всегда является признаком неправильной архитектуры вашей программы.

Звучит так, как будто это ужасно мучительно, но ваше приложение было бы намного лучше — и работало бы с использованием функций ReadPipeAsyncTO и WritePipeAsyncTO — если бы вы переписали его, чтобы использовать цикл выполнения вместо любого ручного цикла, который у вас есть в настоящее время.

person Peter Hosey    schedule 25.07.2010
comment
Можете ли вы дать мне указатель на пример кода, который делает это? Я, конечно, открыт для предложений. В исходном коде использовалась 20-летняя устаревшая функция (GetNextEvent), поэтому изменение архитектуры, вероятно, в любом случае необходимо... - person Brian Postow; 26.07.2010
comment
Делает то, что? Правильно ли использует цикл выполнения? Любое приложение Cocoa, которое не вызывает напрямую CFRunLoopRun или -[NSRunLoop run…] (или, пока мы здесь, -[NSApplication nextEvent::::]), подходит. Цикл выполнения в любом случае существует, и приложение построено на нем, поэтому все, что вам нужно сделать, это запланировать асинхронную операцию с ним, затем закончить, вернуться и позволить ему вернуться к вам в свое время. - person Peter Hosey; 27.07.2010
comment
Скорее всего, вы пытаетесь установить соединение до запуска цикла выполнения. Вы не можете сделать это с помощью цикла выполнения Foundation, хотя вы можете избежать этого, используя цикл выполнения Core Foundation, поэтому у вас все работает наполовину. Вместо того, чтобы инициализировать свой код перед запуском основного цикла выполнения, инициализируйте его как часть подпрограммы, которая уже выполняется в цикле выполнения. Затем ReadPipeAsync[TO] должен работать должным образом. Кроме того, не используйте тайм-аут, если можете помочь. - person dgatwood; 12.04.2014