16

我目前正在设计一个 linux c++ 应用程序。它将从命令行运行,然后一旦运行,我需要能够发出命令来控制其执行,理想情况下如下所示:

$ sudo ./myapplication
APP > 
APP > 
APP > //just pressing return
APP > openlog test1.txt //APP will now call the openlog function
APP >

我想这是一个相对简单的任务,但我不知道会调用什么这样的接口来搜索一个。有人知道可以执行此功能的库或示例吗?还是我需要使用 cout 和 cin 自己编写?如果是这样,是否有任何首选方法?

4

10 回答 10

17

我为此推荐 GNU readline 库。它负责获取输入行的繁琐工作,并允许用户使用退格键、左右箭头等编辑行,并使用向上箭头调用旧命令,甚至使用 ^R 搜索旧命令,等等。Readline 安装了典型的类 unix 发行版,如 linux,但如果你没有它,你可以在这里找到它。

编辑:这是一个最小的 readline 示例:

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>

int main(int argc, char ** argv)
{
    while(1)
    {
        char * line = readline("> ");
        if(!line) break;
        if(*line) add_history(line);
        /* Do something with the line here */
        free(line);
    }
}
于 2012-10-31T23:47:58.660 回答
9

如果您想要完整的行编辑和历史功能, GNU readline库非常棒,但是如果一个简单的提示就足够了(或者如果您不想要 GNU 许可证),那么您可以只使用标准库来做到这一点:

#include <iostream>
#include <string>

void process(std::string const & line);

int main()
{
    for (std::string line; std::cout << "APP > " && std::getline(std::cin, line); )
    {
        if (!line.empty()) { process(line); }
    }

    std::cout << "Goodbye.\n";
}
于 2012-10-31T23:48:21.250 回答
3

正如其他人所建议的那样,GNU readline 是迄今为止一个很好的选择。如果许可问题会迫使您将其排除,那么您应该考虑linenoise

于 2012-11-01T02:37:19.933 回答
2

您可能应该看一下readline 库。它有一点学习曲线,但它仍然比你自己重新创建一个完整的 CLI 容易得多。请检查许可,因为它可能不适合您的项目。

于 2012-10-31T23:44:52.750 回答
2

我同意 Chris 的评论,即在没有反思性的语言中这会更难。在 C++ 中,您需要将您键入的任何内容显式映射到特定函数。

如果你要自己动手,你的一般设计应该是这样的:

  • 读取输入行(很可能使用 cin.getline 到字符串中)
  • 识别第一个单词并确定它是否映射到任何函数(例如,您可以使用简单的 switch 语句、哈希表等)
  • 如果它没有映射到函数,请发布错误并重新打印提示。
  • 如果它确实映射,您必须检查该行中的其他单词。
  • 对于每个其他单词,您必须逐字将字符串转换为您想要的任何数据类型作为函数参数(字符串流在这里会派上用场)。
  • 现在您必须确保您提供的参数对于您调用的函数是合法的。您可以在调用函数之前预先检查它们,或者检查函数内部的错误。
  • 一旦你验证了你的函数名称和参数是正确的(并且是正确的数字),你就可以调用这个函数了。

在反射语言中,前半部分被大大简化了,因为您可以将字符串直接转换为函数名。

于 2012-11-01T00:00:15.510 回答
1

您将必须至少部分滚动自己的。GNU readline 可能会有所帮助;查看http://en.wikipedia.org/wiki/GNU_readline以获得一个简短的程序,它是实现这一目标的“骨架”,您可以在其周围实际添加代码。

于 2012-10-31T23:43:47.937 回答
1

有点晚了,但无论如何...

只是为了让您了解专门为此需求设计 的CLI 工具包项目:http: //sourceforge.net/projects/aroyer-cli/

于 2015-10-09T22:59:33.207 回答
1

请注意 GNU Readline 的 GPL 许可。在答案中,人们提到了 GNU readline 的 GPL 许可证。在这个答案中,我想强调 GPL 许可证的含义——新用户/开发人员可能会忽略它。

从https://en.wikipedia.org/wiki/GNU_Readline复制的文本

选择 GPL 作为 GNU Readline 的许可证[编辑] GNU Readline 是一个自由软件库,它是根据 GNU 通用公共许可证 (GPL) 而不是 GNU 宽通用公共许可证 (LGPL) 授权的。自由软件库通常在 LGPL 下获得许可,例如 GNU C 库、GNU gettext 和 FLTK。

在构建新应用程序时选择链接到 LGPL 许可库的应用程序开发人员在分发组合的结果应用程序时,需要将其使用的 LGPL 许可库保留在 LGPL 之下。组合应用程序中不包括 LGPL 许可库的部分可以保留在原始许可下。 [1] 这与选择使用 GPL 许可库来创建新应用程序的开发人员形成对比,在这种情况下,整个组合生成的应用程序在分发时需要根据 GPL 获得许可,以符合 GPL 第 5 节。 [2 ][3]

GNU Readline 的 GPL 许可证的含义[编辑] 应用程序更改其许可证以符合 GNU Readline 的 copyleft 条件的一个重要示例是 CLISP,它是 Common Lisp 的一个实现。最初于 1987 年发布,1992 年更改为 GPL 许可证,[4] 在 CLISP 的原作者之一布鲁诺·海布尔(Bruno Haible)和理查德·斯托曼(Richard Stallman)之间进行电子邮件交换后,斯托曼认为 [5] CLISP 中的 readline 链接意味着如果 Haible 希望分发使用 readline 的 CLISP 的实现,他必须根据 GPL 重新许可​​ CLISP。[6]

希望实现命令行编辑功能但希望保持在许可许可下的软件项目可以使用获得许可许可的替代命令行编辑库。其中典型的是 BSD 许可的 libedit。一些应用程序,例如 MariaDB[7] 或 PHP[8],允许用户在构建时选择是与 GNU Readline 还是与 libedit 链接。其他命令行编辑库有双重用途:它们具有与某些主要项目的 API 保持一致的 API,并具有兼容的许可条款。这方面的一个例子是 Haskeline 库,它向 Glasgow Haskell 编译器 [9] 和其他需要行编辑服务的 Haskell 项目公开了与 Haskell 兼容的 API。 [10]

外部链接中列出了几个此类库的链接。

于 2018-02-04T00:51:07.360 回答
1

这个似乎完全符合 OP 的要求:

它本质上是 readline 库的包装器,但是将函数的参数解析/转换为它们各自的类型:

shpp::service svc;
svc.provide_command("my_function", [](int arg1, string arg2) -> { /* Do Something */ });
shpp::shell sh(svc);
sh.start();

它适用于函数指针和 lambda。

于 2018-05-17T13:23:16.790 回答
-4

您可以将您的应用程序编写为 TCL 或 python 应用程序并将它们用作前端。

于 2012-10-31T23:23:24.240 回答