总览
我一直在使用ncurses++库编写代码来显示菜单和屏幕。期望的结果是通过串行终端接口(interface)输出这些菜单和屏幕。
目前的尝试
我可以使用调用的基础C ncurses库成功完成此操作。
if( (FDTERM = fopen("/dev/ttyS0", "r+")) != NULL )
{
if(FDTERM == NULL)
{
fprintf(stderr, "Error opening device: %s.\n", ncurses_device);
}
/* Set Screen */
MY_SCREEN = newterm(NULL, FDTERM, FDTERM);
if(MY_SCREEN != NULL)
{
/* Set the terminal */
set_term(MY_SCREEN);
}
}
为了使它在c++中工作,我写了一些intercept.c代码来覆盖对cursesw.cc中对:: initscr()的调用实际上对
#define ncurses_device "/dev/ttyS0"
NCURSES_EXPORT(WINDOW *) initscr(void)
{
WINDOW *result;
pthread_mutex_lock(&CUSTOM_LOCK);
if (!CUSTOM_INITIALIZED)
{
CUSTOM_INITIALIZED = true;
if( (FDTERM = fopen(ncurses_device, "r+")) != NULL )
{
if(FDTERM == NULL)
{
fprintf(stderr, "Error opening device: %s.\n", ncurses_device);
}
/* Set Screen */
MY_SCREEN = newterm(NULL, FDTERM, FDTERM);
if(MY_SCREEN != NULL)
{
/* Set the terminal */
set_term(MY_CDU_SCREEN);
}
/* def_shell_mode - done in newterm/_nc_setupscreen */
def_prog_mode();
}
else
{
CUSTOM_INITIALIZED = true;
NCURSES_CONST char *name;
if ((name = getenv("TERM")) == 0 || *name == '\0')
{
static char unknown_name[] = "unknown";
name = unknown_name;
}
if (newterm(name, stdout, stdin) == 0)
{
fprintf(stderr, "Error opening terminal: %s.\n", name);
result = NULL;
}
}
}
#if NCURSES_SP_FUNCS
#ifdef CURRENT_SCREEN
NCURSES_SP_NAME(def_prog_mode) (CURRENT_SCREEN);
#else
NCURSES_SP_NAME(def_prog_mode) (SP);
#endif
#else
def_prog_mode();
#endif
result = stdscr;
pthread_mutex_unlock(&CUSTOM_LOCK);
return Win(result);
}
Intercept.c允许使用定义好的设备(如果有)。它
还允许initscr()退回到使用当前终端的默认行为。
当用于调试时,此方法有效,但我觉得必须有一种更好的方法来设置NCurses或环境,以通过所需的串行端口定向NCurses输出。
由于没有可用的终端定义,因此在启动时执行代码时,上述解决方案现在不起作用。
正在开发它以同时支持RHEL 7和RHEL6。一些研究似乎指向使用getty,agetty或通过编辑start-tty.conf(如所述)来创建新的环境服务(https://unix.stackexchange.com/a/318647)。
但是另一个问题是将NCurses++指向正确的环境。从我在NCurses源代码中看到的来看,似乎默认是从cursesw.cc调用:: initscr(),这使得将NCurses指向新环境变得更加困难。
问题
如何设置NCurses++以输出到指定的tty?
如何正确设置NCurses在系统启动时使用的环境?
更新1:
更新了代码以执行以下操作:
// Save the current stdin/stdout file descriptors
int saved_stdin = dup(fileno(stdin));
int saved_stdout = dup(fileno(stdout));
// Set the stdin/stdout to the desired device
freopen(ncurses_device, "w+", stdout);
freopen(ncurses_device, "r+", stdin);
// Initialize the NCursesMenu
NCursesMenu *m_pMenu = new NCursesMenu(m_pMenuItems);
// Restore the saved_stdin/stdout to the correct locations
dup2(saved_stdin, STDIN_FILENO);
dup2(saved_stdout, STDOUT_FILENO);
// Close the saved_stdin/stdout file descriptors
close(saved_stdin);
close(saved_stdout);
这允许NCurses复制在 newterm 中定义为here的当前FILE *,但是一旦将stdin/stdout FILE *恢复到保存的文件描述符中,操作就会丢失。如果仅将设备指向新设备,则该设备可用于NCurses,但所有调试/测试信息均不可见,因为它已被当前终端中的NCurses覆盖。
最佳答案
initscr
不假定有关设备的任何信息:它在初始化时使用当前的输入/输出stdin和stdout(并且通过newterm
,setupterm
,它复制文件描述符)。
如果您的应用程序(或环境/脚本)将这些流设置为您要连接的设备,则对于C++接口(interface)而言就足够了。 ncurses不使用C + cout等。
关于c - 从Linux启动时,如何将NCurses输出定向到串行终端?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52636581/