我在我的程序的.Net版本中通过P / Invoke使用三个本机WinApi函数: ReadConsoleOutput,WriteConsoleOutput,ReadConsoleInput。 如何在Linux下的Mono对应项中实现此功能?
我知道standart System.Console类。但是由于一些奇怪的原因,这个类不支持以前提到过的winapi函数的功能。
答案 0 :(得分:1)
如果你重写你的I / O以便它跟踪屏幕本身应该是什么(这些天不应该占用太多内存),并且只使用Console
类进行更新,你会发现Mono的实现可以跟上。 Mono还可以通过Mono.Terminal
namespace访问ncurses功能,但坚持Console
将更加便携。您仍然可以通过SetCursorPosition
方法,BackgroundColor
属性等将其用于定位和颜色。
答案 1 :(得分:0)
对于与ReadConsoleInput等效的功能,可以使用libtermkey库。
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( );
}