Как получить одно нажатие клавиши в D2 (Фобос)? - PullRequest
8 голосов
/ 21 марта 2011

Существует ли простой кроссплатформенный способ получить одно нажатие клавиши в D2 с помощью Phobos?

Например, приглашение «Нажмите любую клавишу для продолжения ...» или интерпретатор Brainfuck.

Все методы, которые я пробовал, требуют нажатия клавиши Enter перед передачей ввода (например, getchar ()).

Ответы [ 2 ]

5 голосов
/ 22 марта 2011

Самое простое решение, которое работает с D2 в Windows:

import std.stdio : writefln;

extern(C) int kbhit();
extern(C) int getch();

void main()
{
    while(!kbhit())
    {
        // keep polling
        // might use Thread.Sleep here to avoid taxing the cpu.
    }

    writefln("Key hit was %s.", cast(char)getch());
}

Может даже работать с D1, но я не пробовал.

Вот версия для Linux, модифицированнаяот пост Вальтера :

import std.stdio : writefln;
import std.c.stdio;
import std.c.linux.termios;

extern(C) void cfmakeraw(termios *termios_p);

void main() 
{
    termios  ostate;                 /* saved tty state */
    termios  nstate;                 /* values for editor mode */

       // Open stdin in raw mode
       /* Adjust output channel        */
    tcgetattr(1, &ostate);                       /* save old state */
    tcgetattr(1, &nstate);                       /* get base of new state */
    cfmakeraw(&nstate);
    tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */

      // Read characters in raw mode
    writefln("The key hit is %s", cast(char)fgetc(stdin));

       // Close
    tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode
}
5 голосов
/ 22 марта 2011

Я провел некоторое исследование по этому вопросу и обнаружил, что, хотя библиотека Фобоса в D 1.0 имела именно то, что вам нужно в форме std.c.stdio.getch(), в D 2.0 отсутствует эта функция. Похоже, что ни одна из других стандартных функций ввода в Фобосе не работает так, как вам нужно.

Насколько я понимаю, это потому, что желаемое поведение (то есть получение одного символа без необходимости нажатия клавиши Enter) является довольно нестандартным и должно быть реализовано относительно некрасиво, специфично для платформы. (В своем первоначальном виде функция getch существовала в C <conio.h>, специфичном для DOS заголовке, который стал своего рода кроссплатформенным стандартом де-факто, несмотря на то, что не являлся частью стандартной библиотеки C . Очевидно, что сопровождающие библиотеки времени выполнения Phobos решили исключить этот конкретный бит обратно совместимой функциональности во имя более чистой библиотеки, но за счет этой функциональности.

Ручное декларирование

По сообщениям , вы можете обойти это пропущенное объявление функции, добавив его в исходный файл:

extern (C) int getch();

Однако я обнаружил, что это приводит к ошибке компоновщика, предполагая, что функция была полностью удалена из библиотеки времени выполнения, а не просто удалена ее декларация из std.c.stdio. Это, безусловно, стоит попробовать - это может сработать на вашей системе и компиляторе, я действительно не знаю.

Редактировать 2: На самом деле это похоже на работу в Windows; это не удалось для меня на стороне Linux. Похоже, что DMD под Windows сначала ссылается на среду выполнения Phobos / D (phobos.lib), а затем среду выполнения C (snn.lib); однако в Linux DMD ссылается на одну библиотеку времени выполнения, которая поставляет обе части. Это различие, по-видимому, приводит к тому, что связь с необъявленными функциями (среди них getch) работает только в Windows. Если Windows - единственная платформа, которая вас интересует, это решение, вероятно, подойдет. Если вам нужна дополнительная кроссплатформенная совместимость, читайте дальше.

Ncurses

Другая возможность - использовать библиотеку ncurses. Он реализует функцию getch, которая определенно будет делать то, что вы хотите - при условии, что вы хорошо умеете находить D-привязки для библиотеки или просто используете интерфейс C. Имейте в виду, что это требует больше настроек smidgen, чем просто вызов нужной функции; эта тема содержит больше информации по этому вопросу.

D 1,0

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

Я считаю, что Tango также потерял свою декларацию getch (под tango.stdc.stdio) из-за перехода на D 2.0, но мои знания о Tango крайне ограничены, поэтому я могу ошибаться.

Напиши сам

Если вы полны решимости, вы можете просто написать свой getch. Я не смог найти кроссплатформенную реализацию C getch с использованием Google Code Search , что оставляет меня пессимистичным в отношении вероятности относительно простой реализации функции из 10 строк или около того, что можно просто адаптировать к D.

С другой стороны, Уолтер Брайт - вы знаете, парень, который разработал язык D - обеспечивает реализацию D именно такой функции здесь . Однако даже это выглядит несколько устаревшим, поскольку один из символов cfmakeraw не определен в текущей версии компилятора DMD2. Тем не менее, это действительно близко к тому, чтобы быть работоспособным решением.

...