我一直在使用ncurses ++库编写代码来显示菜单和屏幕。理想的结果是通过串行终端接口输出这些菜单和屏幕。
我可以使用调用的基础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和RHEL7。一些研究似乎指向使用getty,agetty或通过编辑start-tty.conf来创建新的环境服务(如https://unix.stackexchange.com/a/318647)。
但是另一个问题是将NCurses ++指向正确的环境。根据我在NCurses源代码中看到的内容,似乎默认情况下从cursesw.cc调用:: initscr(),这使得将NCurses指向新环境变得更加困难。
如何设置NCurses ++以输出到指定的tty?
如何正确设置NCurses在系统启动时使用的环境?
更新的代码可以执行以下操作:
// 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覆盖。
答案 0 :(得分:1)
class CreateTypeControlAccesses < ActiveRecord::Migration
def change
create_table :type_control_accesses do |t|
t.string :name
t.timestamps null: false
end
end
end
对设备没有任何假设:初始化时会使用 current 输入/输出 stdin 和 stdout (并通过initscr
,newterm
复制文件描述符)。
如果您的应用程序(或环境/脚本)将这些流设置为您要连接的设备,则对于C ++接口应该足够了。 ncurses不使用C + cout 等。