C ++ - 创建一个事件循环

时间:2012-03-29 17:23:31

标签: c++ events event-loop

有没有人知道如何在没有库的情况下在c ++中创建事件循环?它不一定是跨平台的,我在Mac上。基本上,我希望程序运行并且什么也不做,直到用户按下向上箭头键,然后程序将输出“你按下”或其他东西。我能想到的就是拥有一个无限whilefor循环并获得cin的输入,但我不认为cin可以检测到箭头键,我相信它暂停程序直到达到'\ n';

我希望它看起来像这样:

void RUN()
{
   while(true)
   {
      // poll events and do something if needed
   }
}

int main()
{
   RUN();
}

我确信没有线程是可能的,我听说这可以用fd_set或其他东西来完成,但我不确定如何。

任何帮助都会非常感激。

修改

当没有任何事件时,程序在后台运行。例如,Microsoft Word在用户按下按钮之前不会停止,它会一直运行。我想要这样的东西,但命令行不是GUI。

4 个答案:

答案 0 :(得分:1)

由于您正在谈论键盘输入,而不是寻找Mac外观,所以您想要的是UNIX的方式。就是这样,

1)将终端设置为raw或cbrk模式(我忘了哪个)。 2)现在使用read()一次读取单个字符。 3)暂时回显字符读取(作为int),这样你就可以找到向上箭头键给你的东西了。

对于更一般的事件循环问题,唯一的输入设备是键盘,你坐在一个循环中,每当键入一个键(在原始模式?),你调用一个例程,键入键的值。如果你有更多的输入设备,你需要多个线程,每个线程可以监听不同的设备,将他们在队列中找到的内容(具有适当的锁定)。然后,主循环将检查队列并在每次出现某些内容时适当地调用例程。

答案 1 :(得分:1)

您可以使用ncurses并启用cbreak来获取原始输入流。

答案 2 :(得分:-1)

我使用了带信号处理程序的while循环。就像这个不完整的片段一样。

void getSomething()
{
  std::cout << "Enter new step size: "; std::cout.flush();
  std::cin >> globalVariable;
  std::getchar();  // consume enter key.
}

void printCommands()
{
  std::cout << "1: do something\n"
        << "q: quit\n"
    << "h: help\n"
    << std::endl;
}

void getCommand()
{
  // Output prompt 
  std::cout << "Enter command ('h' for help): "; std::cout.flush();

  // Set terminal to raw mode 
  int ret = system("stty raw"); 

  // Wait for single character 
  char input = std::getchar(); 

  // Reset terminal to normal "cooked" mode 
  ret = system("stty cooked"); 

  std::cout << std::endl;

  if (input == 'h') printCommands();
  else if (input == '1') getSomething();
  else if (input == 'q') {
    g_next = true;
    g_quit = true;
  } 
}

void 
signalHandler(int signo)
{
  if (signo == SIGINT) {
    g_next = true;
  } else if (signo == SIGQUIT) {
    getCommand();
  }
}

int main(int argc, char* argv[])
{
  signal(SIGINT, signalHandler);
  signal(SIGUSR1, signalHandler);
  signal(SIGQUIT, signalHandler);

  do {
    // Stuff
  } while (!g_quit);

  exit(0);
}

答案 3 :(得分:-1)

问题已经更新,说“程序必须在后台运行......但命令行不是GUI。”

所有传统; *可以将程序放入后台的NIX shell也会断开程序从终端的标准输入,因此AFAIK,这已经不可能了。


这不需要特定于Mac。 Mac支持* NIX机制,用于从键盘读取字符。

AFAICT所有程序正在做的是等待一个字符,所以它不妨阻止。

通常终端设备tty(teletype!)正在解释键盘上键入的字符,然后程序才能从标准输入读取它们。具体来说,tty设备通常缓冲整行文本,并截取rubout字符(以及其他一些像CTRL + w)来编辑文本行。这种字符预处理称为“线条规则”

您需要设置tty设备驱动程序以停止这样做!然后,您可以获得用户输入的所有字符。

您可以使用文件描述符上的ioctl或termios更改设备。

搜索例如“ioctl tty line discipline raw”了解细节,并找到程序示例。

您可以使用命令行程序stty将终端设置为“原始”。 请阅读stty手册页,因为将其设置回来可能会有点棘手(注意:如果你犯了一个错误,通常更容易杀死终端,而不是尝试修复它,因为没有你输入的任何东西的回声)

向上箭头可能不是单个字符,因此它需要一些一次一个字节的解码,以避免在输入流中的错误点处阻塞,即,如果某些输入序列是一个字符,以及其他两个或三个字符,解码需要在每个字节处发生,以确定是否存在未决字节,或者可能会发出一个太多的读取,这将导致程序阻塞。