Как я могу легко перенаправить вывод консоли в NSTextView? - PullRequest
0 голосов
/ 22 октября 2010

Предположим, у вас есть код приложения Какао, которое записывает свои собственные сообщения через NSlogs и printfs на вывод консоли.Моя цель состоит в том, чтобы перенаправить весь этот вывод в отдельное окно NSW в NSView.

Как я могу добиться этого таким образом, чтобы

  • минимизировал объем кода для перезаписи
  • позволяет вернуть обратно
  • максимизирует повторное использование написанного кода

(обычные инструкции по разработке программного обеспечения)?

Ответы [ 3 ]

3 голосов
/ 22 октября 2010
  1. Вскоре после запуска вашей программы используйте вызов dup (2) для создания дубликатов дескрипторов файлов для fd 1 (stdout) и 2 (stderr).Сохраните возвращенные значения для дальнейшего использования.

  2. Вызовите close (2) для FD 1 и FD 2.

  3. Дважды вызовите openpty (2).Первый возвращенный мастер должен быть FD 1 (потому что это первый доступный FD), а второй мастер должен быть 2. Сохраните два подчиненных FD на потом.Не беспокойтесь о сохранении параметра name.Теперь, когда ваша программа printf (2) в stdout или NSLogs для stderr, данные будут записываться на ваши подчиненные FD.

  4. Теперь вы должны выбрать, хотите ли вы опросить подчиненные FD илиустановите сигнал, когда есть данные для чтения.

Для опроса используйте NSTimer.В вашем таймере используйте select (2) на двух подчиненных FD, чтобы увидеть, есть ли у них данные.Если они читают (2), а затем выводят его в ваше окно.Вы также можете заставить два подчиненных FD использовать неблокирующий IO (используйте fcntl (2), чтобы F_SETFL подчиненных FD обращался к O_NONBLOCK).Тогда вам не нужно выбирать (2), вы просто читаете (2), и он вернет ноль, если нечего читать.

Для сигнализации используйте fcntl (2) для F_SETFL подчиненных FD для O_ASYNC,Затем используйте сигнал (3) для установки обработчика сигнала для SIGIO.Когда вызывается ваш обработчик сигнала, используйте один из двух методов, которые я описал в разделе опроса.

Если во время выполнения вы хотите отменить все эти изменения и вернуть все в нормальное состояние, сделайте следующее:

  1. Вызовите close (2) на FD 1 и FD 2.

  2. Вызовите dup (2) на двух FD, сохраненных с шага 1 в первом разделе,выше.Сделайте dup (2) в правильном порядке, чтобы stdout использовал FD 1, а stderr использовал FD 2.

Теперь все, что записано в stdout и stderr, перейдет к исходным FD.

1 голос
/ 22 октября 2010

Как насчет написания вашего собственного метода журнала, который информирует некоторый контроллер о сообщении журнала (чтобы он мог поместить его в представление (NSTextView?), А затем по очереди вызывает NSLog ()?

0 голосов
/ 23 октября 2010

Вот решение, которое я придумал:

  1. Создайте NSWindowController с NSTextView в качестве выхода (назовем это A )
  2. Создатькласс Singleton (назовем это B ), который инкапсулирует объект A и предоставляет некоторые методы для отправки строк в A (который добавляет его в свой NSTextView), читая файл (который содержит все записи), используя readInBackgroundAndNotify из NSFileHandle.При получении уведомления вызывается добавляющий метод.У него также есть метод для запуска регистрации в файле, который использует freopen(3) для перенаправления некоторого потока (stderr и stdout atm) в файл в режиме добавления.
  3. В проекте просто вызовите начальный метод регистрациипосле B (не нужно создавать экземпляры, но я думаю, это действительно не имеет значения) после его импорта.

Это решение было создано с учетом как ответа Джошуа Ноцци, так и ответа Тлинднера, и объединяет их.У меня есть и инкапсулированное решение, которое учитывает три запроса в вопросе (мне нужно добавить только строку кода, я могу легко вернуться назад и использовать это решение также и в других приложениях).Я заметил, что, возможно, иногда может быть неправильно инкапсулировать NSWindowController таким образом (тогда как все остальные управляются каким-то суперконтроллером).

Я наконец выбрал файловое решение, так как это очень легкореализовать и больше похож на какао, чем у Тлинднера.Также это дает возможность иметь файл журнала, который сохраняется на диске.Но, конечно, я мог что-то упустить, укажите это мне в комментариях, пожалуйста ^^

...