Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Место, где разработчики плагинов могут поделиться своим опытом.
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

Предположим, я использую стороннюю библиотеку, которую линкую в плагин, т.е., ее код исполняется непосредственно в процессе Фара.

И вот эта библиотека где-то там у себя внутри вдруг пишет в stdout (и stderr) всякое, и оно, соответственно, прям поверх красивого синего Фара серым цветом изображается.

Кто-нибудь с такой проблемой сталкивался и решал ли? Какие идеи? Тупейшее лобовое закрытие перед вызовом, а потом переоткрытие stdout'а после -- не срабатывает, то есть надо ковыряться. Понятно, что так или иначе проблему решить можно, но, может, в Фаре есть какая-то готовая функциональность для этого?
User avatar
DrKnS
Posts: 6114
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 12 times
Been thanked: 426 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by DrKnS »

Если вы будете играться с перенаправлением stdout, то поломаете вывод самого фара.
Кроме того, ничто не мешает библиотеке напрямую открывать CONOUT$.
Поэтому или уносить в отдельный процесс, или просить автора библиотеки так не делать.
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

А если известно, что код библиотеки использует *только* стандартный fprintf stdout/stderr?
User avatar
DrKnS
Posts: 6114
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 12 times
Been thanked: 426 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by DrKnS »

Стандартный наверное можно заткнуть каким нибудь freopen("nul","w",stdout).
Только не забудьте потом поставить обратно, т. к. другие могут использовать его для вполне легитимных целей.
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

Вот как раз "поставить назад" не получалось. То есть, и полное закрытие и перенаправление работало, а когда потом "ставил назад", фар затихал секунды на 3 и падал.

Я, в общем, не копал, просто решил сначала спросить, чтоб, в случае чего, не ломиться в открытые ворота. Ну, покопаю тогда.
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by Shmuel »

Как вариант может сгодиться обёртка вызовов функций библиотеки парой FCTL_GETUSERSCREEN/FCTL_SETUSERSCREEN.
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

В общем, проблему нашел, к ФАРу она отношения не имеет. На всякий случай напишу тут, а то вдруг кто напорется.

Проблемой является откровенный маразм в заголовочных файлах M$.
В corecrt_wstdio.h (это Windows 10 SDK -- у них теперь CRT частично в Windows SDK входит) написано такое:

Code: Select all

    typedef struct _iobuf
    {
        void* _Placeholder;
    } FILE;
Т.е., любой код, который копирует структуру FILE, копирует только sizeof(void*) байтов. И мой код

Code: Select all

*stdout = ...
(это я stdout "на место возвращаю") в том числе.

И если переопределить структуру FILE нормально (как например, в mingw-w64), или скопировать нужное количество байтов руками, то всё начинает работать нормально.

Ну, я, типа, понимаю, что правильные с точки зрения MS разработчики не должны хотеть копировать структуру FILE, а должны воспринимать ее сугубо как opaque и никогда не разыменовывать указатели на нее. Но вообще, это дичь какая-то. Похоже, это у них началось с момента перетряхивания структуры CRT.
User avatar
DrKnS
Posts: 6114
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 12 times
Been thanked: 426 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by DrKnS »

awson wrote: Но вообще, это дичь какая-то.
Почему дичь? Стандарт явно запрещает разыменовывать и копировать FILE*, содержимое и размер структуры нигде не оговорены и ваше ручное копирование байтов вполне может вычурно отвалиться при первом же апдейте CRT.
Лучше использовать что-то типа _fdopen(_dup(_fileno(stdout)), "w").
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

stdout это rvalue, вы не можете ему ничего присвоить.

написать

Code: Select all

stdout = _fdopen(old_stdout, "w")
нельзя.

Вы сначала делаете

Code: Select all

int old_stdout = _dup(1)
потом зовете нужную функцию, а потом "возвращаете" stdout с помощью

Code: Select all

*stdout = * _fdopen(old_stdout, "w")
Но если стандарт запрещает копировать FILE, значит либо подобные вещи в общем случае вообще нельзя делать, либо делать не на уровне CRT.
User avatar
DrKnS
Posts: 6114
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 12 times
Been thanked: 426 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by DrKnS »

  1. printf("this goes to screen\n");
  2.  
  3. fflush(stdout);
  4.  
  5.  
  6.  
  7. int fd = _dup(_fileno(stdout));
  8.  
  9. freopen("out.txt", "w", stdout);
  10.  
  11.  
  12.  
  13. printf("this goes to file\n");
  14.  
  15. fflush(stdout);
  16.  
  17.  
  18.  
  19. _dup2(fd, _fileno(stdout));
  20.  
  21.  
  22.  
  23. printf("this goes to screen again\n");
  24.  
  25. fflush(stdout);
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

Ничо не понял, но не работает :)
Last edited by awson on Thu 29 Dec, 2016 21:21, edited 2 times in total.
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by Shmuel »

awson wrote: Ничо не понял, но не работает :)
У меня почему-то работает.
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

Shmuel wrote:У меня почему-то работает.
Чтобы не работало, нужен *новый* Windows 10 SDK, который ставится, например, с VS 2017RC и, возможно, с VS2015. У меня есть гипотеза, что с более старыми студиями (до перетряски CRT) оно тоже работает, как, например, оно прекрасно работает с mingw-w64 gcc.

Под новым Windows 10 SDK код уважаемого DrKnS падает, хотя он, судя по всему, корректнее, поскольку не копирует FILE.
User avatar
DrKnS
Posts: 6114
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 12 times
Been thanked: 426 times

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by DrKnS »

У меня на VS2015, SDK v10.0.10240.0 всё работает.
FILE там такой же, как у вас выше.
Если в 2017RC падает - возможно, это баг, есть смысл написать им на https://connect.microsoft.com/VisualStudio
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сторонняя библиотека, *линкуемая* в плагин, пишет в stdout (stderr)

Post by awson »

Ха, у меня оказался немного другой код (там был еще fclose(stdout), а потом _fdopen ...), так вот он падал на 2015 и 2017 и работал на 2012 (откопал ее и проверил) и mingw-w64. Я сейчас в точности воспроизвел ваш и он действительно работает на всех версиях.

Вопросы снимаются.
Post Reply

Return to “Разработка плагинов”