如何在使用GNU readline从stdin读取时将消息输出到另一个线程上的stdout而不会弄乱输入?

时间:2011-02-21 17:00:23

标签: c pthreads readline libreadline

很抱歉这个长标题。我正在用C开发一个网络程序,它可以在stdout上显示从网络接收的消息,并通过GNU readline库接受stdin上的用户输入。 问题是,当用户通过readline在主线程上键入命令时,网络消息到达并输出到stdout,这将生成如下内容:

场景:

  

输入:1234567890
  网络留言:您好   当用户输入“7”

时,网络消息到达

终端上的实际输出:

  

输入和GT; 1234567Hello
  890_

有没有办法让输出像这样?

  

您好
  输入> 1234567890_

P.S。 _是光标。

提前致谢!

4 个答案:

答案 0 :(得分:6)

好的,我在搜索后找到了解决方法,并将以下替换为printf()。通过使用rl_replace_line(“”,0)它将清除当前行并将光标放在行的开头,然后我可以打印一行消息,然后恢复readline提示,将原始行替换回原位,并且恢复光标位置 但是,这个hack需要调用这个printf函数才能在最后包含一个\ n,否则该行将被readline覆盖。

#define printf(...) my_rl_printf(__VA_ARGS__)
void my_rl_printf(char *fmt, ...)
{
    int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0;
    char *saved_line;
    int saved_point;
    if (need_hack)
    {
        saved_point = rl_point;
        saved_line = rl_copy_text(0, rl_end);
        rl_save_prompt();
        rl_replace_line("", 0);
        rl_redisplay();
    }

    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);

    if (need_hack)
    {
        rl_restore_prompt();
        rl_replace_line(saved_line, 0);
        rl_point = saved_point;
        rl_redisplay();
        free(saved_line);
    }
}

答案 1 :(得分:1)

转储readline并阅读用户输入的每个char。如果您在用户输入清除当前行时收到任何网络消息,请输出网络消息,然后重新打印用户当前正在输入的行。

这可能看起来很多,但这是我现在想到的唯一方法。

如果您转储readline,那么您可以使用curses,这样可以更轻松...

答案 2 :(得分:0)

你应该在这两个线程之间进行某种同步。互斥锁或只是从一个线程到另一个线程的标志,表明它正在stdin或stdout上工作。

答案 3 :(得分:0)

可以使用curses(3)库完成此操作。