Поэтому я пытался читать и писать из Pianobar (консольный плеер Pandora) STDIN и STDOUT, чтобы управлять им из другого приложения.
Тем не менее, для некоторых при чтении из STDOUT он полностью блокируется в последней строке (где он отображает время песни).
Я думал, что делал что-то не так (вероятно, все еще), но я скачал демонстрационный проект для отправки / получения входных данных в другие приложения STDIN / STDOUT через пару дескрипторов.
Итак, я углубился в код Pianobar и вставил команды printf повсеместно, чтобы отследить, где происходил блок (это правильное слово для блока?). В любом случае, я, наконец, попадаю в раздел кода, который, кажется, зацикливается очень быстро, когда создается как дочерний процесс, а также блокирует STDOUT.
От Pianobar, замена ui_readline.c BarReadline
/* readline replacement
* @param buffer
* @param buffer size
* @param accept these characters
* @param input fds
* @param flags
* @param timeout (seconds) or -1 (no timeout)
* @return number of bytes read from stdin
*/
size_t BarReadline (char *buf, const size_t bufSize, const char *mask,
BarReadlineFds_t *input, const BarReadlineFlags_t flags, int timeout)
{
// took out some extra code from here ...
printf("In BarReadline 005\n");
fflush(stdout);
while (true) {
Sleep(400); // added this to stop it from doing 100% on a core
printf("In BarReadline 006\n");
fflush(stdout);
if (timeout != INFINITE) {
DWORD now = GetTickCount ();
printf("In BarReadline 007\n");
fflush(stdout);
if ((int)(now - timeStamp) < timeout) {
timeout -= (int)(now - timeStamp);
timeStamp = now;
}
else
timeout = 150; // KYLE changed from 0
}
printf("Current timeout: %d\n",timeout);
printf("In BarReadline 008\n");
fflush(stdout);
waitResult = WaitForSingleObject (handle, timeout);
printf("In BarReadline 009\n");
fflush(stdout);
if (WAIT_OBJECT_0 == waitResult) {
INPUT_RECORD inputRecords[8];
INPUT_RECORD* record;
DWORD recordsRead, i;
printf("In BarReadline 010\n");
fflush(stdout);
successConsole = ReadConsoleInput (handle, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &recordsRead);
if(successConsole != 0) {
printf("We read from console\n");
}
printf("In BarReadline 011\n");
fflush(stdout);
for (i = 0, record = inputRecords; i < recordsRead; ++i, ++record) {
int codePoint, keyCode;
printf("In BarReadline 012\n");
fflush(stdout);
И код выше распечатывает:
In BarReadLine 005
In BarReadline 006
In BarReadline 007
Current timeout: 150
In BarReadline 008
In BarReadline 009
In BarReadline 010
In BarReadline 011
In BarReadline 006
In BarReadline 007
Current timeout: 150
In BarReadline 008
In BarReadline 009
In BarReadline 010
In BarReadline 011
В любом случае, я могу нажать клавишу «ввод» в демонстрационном приложении Redirect с помощью известного ключа, который не требует ничего особенного, он просто продолжает вращаться в этом цикле и, кажется, не перехватывает его, что для меня звучит как один из две вещи; У нас нет доступа к функции INPUT, так как она блокируется чтением STDOUT, или ReadConsoleInput не распознает то, что мы отправляем из демонстрации Redirect.
Это то, что мне нужно отправить с каким-либо типом асинхронного процесса ввода-вывода? И почему использование «cmd» и открытие обычной командной строки не вызывает блокировку, но это делает?
Обновление 1: Мне удалось построить INPUT_RECORD для отправки на ReadConsoleInput в Pianobar (дочерняя консоль). Тем не менее, я обнаружил, что мое родительское приложение возвращает «неверный дескриптор», когда я пытаюсь отправить WriteConsoleInput(m_hStdinWrite, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &dwWritten);
Существуют ли разные виды ручек для детской консоли STDIN? Использование WriteFile работает, но я не могу отправить INPUT_RECORDs таким образом.
Pianobar Windows Build Environment
Помогло, но не уверен, что вызывает неправильный дескриптор:
Низкоуровневый ввод и перенаправление консоли
Я считаю, что это потому, что программа использует ReadConsoleInput вместо ReadFile. ReadConsoleInput требует дескриптор консоли.
Вам нужно будет создать консоль и передать ее дескриптор. Тогда вам нужно будет записать в него события ввода с консоли.
Было бы лучше, если бы вы могли изменить другую программу, чтобы она просто использовала ReadFile, если бы вы могли заставить это работать.
Других решений пока нет …