C++-生成一个事件循环

C++ - Making an event loop

本文关键字:一个 事件 循环 C++-      更新时间:2023-10-16

有人知道如何在没有库的情况下在c++中进行事件循环吗?它不一定是跨平台的,我在Mac上。基本上,我希望程序运行,在用户按下向上箭头键之前什么都不做,然后程序会输出"You pressed up"或其他什么。我所能想到的就是有一个无限的whilefor循环,并用cin获得输入,但我不认为cin能检测到箭头键,我相信它会暂停程序,直到达到'\n';

我希望它看起来像这样:

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

我有点确定这在没有线程的情况下是可能的,我听说这可以用fd_set或其他东西来实现,但我不确定如何实现。

如有任何帮助,我们将不胜感激。

编辑:

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

既然你说的是键盘输入,而不是Mac的外观,你想要的是UNIX的方式

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

至于更常见的事件循环问题,在唯一的输入设备是键盘的情况下,你坐在一个循环中,每当键入一个键时(在原始模式下?),你就会用键入的键的值调用一个例程。如果你有更多的输入设备,你将需要多个线程,每个线程都可以监听不同的设备,将他们发现的内容放在队列中(带有适当的锁定)。然后,主循环将检查队列,并在每次有东西出现时适当地调用例程。

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

我在信号处理程序中使用了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 somethingn"
        << "q: quitn"
    << "h: helpn"
    << 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);
}

问题已经更新为"程序必须在后台运行…但命令行而不是GUI。"

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


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

AFAICT程序所做的一切都是等待一个字符,所以它还不如阻止。

通常情况下,终端设备tty(电传!)在您的程序从标准输入读取字符之前,正在解释键盘上键入的字符。具体来说,tty设备通常会缓冲整行文本,并截取删除字符(以及其他一些字符,如CTRL+w)来编辑这行文本。这种字符的预处理被称为"线条规则"

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

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

搜索例如"ioctl tty line instruction raw"以了解详细信息,并查找程序示例。

您可以使用命令行程序stty将终端设置为"原始"。请阅读stty手册页,因为将其向后设置可能有点棘手(注意:如果你犯了错误,杀死终端通常比修复它更容易,因为你键入的任何内容都没有回音)

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