Функции ReadConsoleOutput, WriteConsoleOutput, ReadConsoleInput в Mono под Linux - PullRequest
0 голосов
/ 09 августа 2009

Я использую в .Net версии моей программы три родные функции WinApi через P / Invoke: ReadConsoleOutput , WriteConsoleOutput , ReadConsoleInput . Как реализовать эту функциональность в Mono-аналоге под Linux?

Я знаю о стандартном классе System.Console. Но этот класс по какой-то странной причине никак не поддерживает функциональность ранее упомянутых winapi-функций.

Ответы [ 2 ]

1 голос
/ 09 августа 2009

Если вы переписываете свой ввод / вывод так, чтобы он отслеживал то, что должно быть на самом экране (который не должен занимать слишком много памяти в наши дни), и обновлялся только с использованием класса Console, вам следует обнаружить, что реализация Mono может идти в ногу. Mono также имеет доступ к функциональности ncurses через пространство имен Mono.Terminal , но придерживаться Console будет более переносимым. Вы все еще можете использовать его для позиционирования и цвета, используя метод SetCursorPosition, свойство BackgroundColor и т. Д.

0 голосов
/ 27 февраля 2014

Для эквивалентной функциональности для ReadConsoleInput можно использовать libtermkey library.

ReadConsoleOutput невозможен в Linux, но вы можете сохранить данные в пользовательском экранном буфере. WriteConsoleOutput может быть легко реализован с помощью NCurses .

Посмотрите на цикл событий, реализованный на платформах Windows и Posix. Основные используемые функции: poll (), pipe (), writeInt64 (), readInt64 () - из стандартной libc:

termkeyHandle = LibTermKey.termkey_new( 0, TermKeyFlag.TERMKEY_FLAG_SPACESYMBOL );

// Setup the input mode
Console.Write( "\x1B[?1002h" );
pollfd fd = new pollfd( );
fd.fd = 0;
fd.events = POLL_EVENTS.POLLIN;

pollfd[ ] fds = new pollfd[ 2 ];
fds[ 0 ] = fd;
fds[ 1 ] = new pollfd( );
int pipeResult = Libc.pipe( pipeFds );
if ( pipeResult == -1 ) {
    throw new InvalidOperationException( "Cannot create self-pipe." );
}
fds[ 1 ].fd = pipeFds[ 0 ];
fds[ 1 ].events = POLL_EVENTS.POLLIN;

while ( true ) {
    int pollRes = Libc.poll( fds, 2, -1 );
    if ( pollRes == 0 ) throw new InvalidOperationException( "Assertion failed." );
    if ( pollRes == -1 ) {
        int errorCode = Marshal.GetLastWin32Error();
        if ( errorCode != Libc.EINTR ) {
            throw new InvalidOperationException(string.Format("poll() returned with error code {0}", errorCode));
        }
    }

    bool needProcessInvokeActions = false;
    if ( fds[ 1 ].revents != POLL_EVENTS.NONE ) {
        UInt64 u;
        Libc.readInt64( fds[ 1 ].fd, out u );
        if ( u == 1 ) {
            // Exit from application
            break;
        }
    }

    if ( ( fds[ 0 ].revents & POLL_EVENTS.POLLIN ) == POLL_EVENTS.POLLIN ||
         ( fds[ 0 ].revents & POLL_EVENTS.POLLHUP ) == POLL_EVENTS.POLLHUP ||
         ( fds[ 0 ].revents & POLL_EVENTS.POLLERR ) == POLL_EVENTS.POLLERR ) {
        LibTermKey.termkey_advisereadable( termkeyHandle );
    }

    while ( ( LibTermKey.termkey_getkey( termkeyHandle, ref key ) ) == TermKeyResult.TERMKEY_RES_KEY ) {
        processLinuxInput( key );
    }

    renderer.UpdateRender( );
}
...