Перенаправить поток FILE * в пользовательский обработчик в Qt

Я хотел бы интегрировать библиотеку C в свой проект C++/Qt. Библиотека принимает поток FILE* для печати отладочных сообщений (вместо предоставления перехватчика для функции обратного вызова ведения журнала...).

Это работает правильно, если я просто передаю stderr, но я хотел бы интегрировать это в свою собственную инфраструктуру ведения журнала, которая использует qDebug() и другие.

Моя первоначальная идея состояла в том, чтобы использовать socketpair(), получить поток FILE* fd отправляющей стороны, передать его в библиотеку и обработать принимающую сторону с помощью QSocketNotifier, но я столкнулся с двумя проблемами:

  • Он не мультиплатформенный, хотя есть реализации для Windows.
  • Мое приложение является однопоточным (и я хочу, чтобы оно оставалось таким), и это означает, что 2 сокета пары сокетов записываются и читаются из одного и того же потока. Кажется, через некоторое время это заканчивается тупиком.

Какие существуют другие методы предоставления потока FILE*, интеграции его чтения в цикл событий Qt, не требующего нескольких потоков и мультиплатформенного?


person zgyarmati    schedule 16.07.2017    source источник
comment
Это общедоступная библиотека C? Если да, то какой? Может быть, вы можете изменить его довольно легко.   -  person Holt    schedule 16.07.2017
comment
Вызов функций C из C++ не подходит для C-тега.   -  person too honest for this site    schedule 16.07.2017
comment
@Holt, libgps от gpsd, я мог бы это исправить, но это последний вариант (предположим, я хочу распространять программу и не хочу отправлять с ней модифицированную библиотеку). Я рассмотрю возможность отправки патча в проект.   -  person zgyarmati    schedule 16.07.2017


Ответы (1)


Пока вы можете получить дескриптор файла в хранилище, вы можете получить FILE* из него, используя непереносимый fdopen в Linux и _fdopen в Windows.

Вы также можете создать обычный канал как в Linux, так и в Windows, используя pipe/_pipe.

И канал должен интегрироваться с циклом событий Qt. Я не знаком с API-интерфейсами Qt, возможно, для этого он предоставляет переносимые API-интерфейсы. Возможно, вы можете использовать класс QLocalSocket:

Класс QLocalSocket предоставляет локальный сокет. В Windows это именованный канал, а в Unix — сокет локального домена.

У него есть метод qintptr QLocalSocket::socketDescriptor() const, который возвращает дескриптор файла, который можно обернуть с помощью fdopen, чтобы создать файл FILE*.

person Maxim Egorushkin    schedule 16.07.2017
comment
Вызов функций Qt из обработчиков сигналов Unix дает полезные советы, связанные с каналом обманывать себя - person Basile Starynkevitch; 16.07.2017
comment
@BasileStarynkevitch В этом примере можно просто использовать один канал для всех сигналов, записывающих в него signo, а не socketpair для каждой передачи бесполезных данных. - person Maxim Egorushkin; 16.07.2017
comment
@MaximEgorushkin, я хочу настроить сообщения (с префиксом временной метки, тегом типа [DGB] и т. д.), поэтому прямой доступ к хранилищу не вариант. Я собираюсь попробовать pipe(), спасибо. - person zgyarmati; 16.07.2017
comment
@BasileStarynkevitch, да, я знаю это, но он использует socketpair(), о котором я упоминал в своем вопросе. - person zgyarmati; 16.07.2017