【问题标题】:How to interface with an executable in C++如何与 C++ 中的可执行文件交互
【发布时间】:2010-07-16 20:36:42
【问题描述】:

我有一个可执行文件,我需要在 C++ 中运行一些测试 - 测试将在所有 Windows、Linux 和 Mac OS 上进行。

我希望输入以下内容:

  • 如何与我的代码中先前构建的可执行文件交互?我可以使用某种命令功能吗?此外,由于我认为操作系统之间的命令会发生变化,因此我需要一些指导来弄清楚如何为所有三个操作系统构建结构。

编辑 - 接口 = 我需要能够使用我的 C++ 代码中的命令行参数运行可执行文件。

  • 从命令行调用的可执行文件还会在控制台上输出一些文本 - 我将如何获取该输出流(我需要记录这些输出值作为测试的一部分)。

随时问我跟进问题。

干杯!

【问题讨论】:

  • “与先前构建的可执行文件的接口”是什么意思?您是否需要使用某些命令行参数启动它并记录输出?如果不止于此,那是什么? “接口”是一个很模糊的词。
  • 是的,只需从我的 C++ 代码中调用可执行文件以及命令行参数即可;还在我原来的问题中添加了一个编辑。

标签: c++ operating-system automated-tests executable


【解决方案1】:

如果您使用 qt 开发代码,您会发现 QProcess 将允许您以与平台无关的方式生成命令行程序。

基本上:

 QObject *parent;
 QString program = "yourcommandlineprogram";
 QStringList arguments;
 QProcess *myProcess = new QProcess(parent);
 myProcess->start(program, arguments);

然后您可以使用各种函数调用(例如 readAllStandardOutput())从进程中读取,并使用 QProcess::write(QString) 写入进程的输入。

或者,如果您更喜欢 Boost 而不是 Qt,Boost.Process 也可以让您启动进程。我承认我不太喜欢这种语法......

boost::process::command_line cl("yourcommandlineprogram");
cl.argument("someargument");
boost::process::launcher l;
l.set_stdout_behavior(bp::redirect_stream);
l.set_merge_out_err(true);
l.set_work_directory(dir);
boost::process::child c = l.start(cl);

然后,您可以使用流运算符 > 来读取和写入子进程“c”。

【讨论】:

  • 听起来不错,但在项目的这个阶段涉及 Qt 可能不会发生:(
  • 我添加了一个关于使用 boost 的注释;作为一个只有头文件(大部分)的库,它可能更容易集成,并且您不需要重新组织任何现有代码。
  • Boost 可能是 OP 案例中的方法。 Boost 是一个库,因此以任何方式包含它都没有任何问题,而且它与平台无关。
【解决方案2】:

所有这些操作系统都支持某种形式的“子进程”调用技术,您的测试人员会在其中创建一个新的子进程并在那里执行被测代码。您不仅可以通过命令行,还可以将管道连接到子进程的标准输入和输出流。

不幸的是,没有标准的 C++ API 来创建子进程。您必须为每个操作系统找到合适的 API。例如,在 Windows 中,您可以使用 CreateProcess 函数:MSDN: Creating Processes (Windows)

另见Stackoverflow: How do you spawn another process in C?

【讨论】:

    【解决方案3】:

    据我了解,您希望:

    1. 使用在运行时未知的参数生成一个新进程。
    2. 检索新进程打印到stdout的信息。

    诸如 QProcess 之类的库可以生成进程,但是,我建议在 Windows 和 MacOS/Linux 上手动执行,因为在这种情况下使用 QProcess 可能是多余的。

    对于 MacOS/Linux,我会这样做:

    1. 在父进程中设置pipe。将管道的读取端设置为父级中的新文件描述符。
    2. fork
    3. 在新创建的子进程中,将 stdout(文件描述符 #1)设置为管道的写入端。
    4. execvp 在新创建的子进程中传递目标可执行文件以及您要为其提供的参数。
    5. 从父进程,wait 为子进程(可选)。
    6. 从父进程中读取您在步骤 1 中指定的文件描述符。

    【讨论】:

    • 那么为什么你给我的这组步骤只针对 Mac/Linux?如果 内置在 C++ 中,那么操作系统应该无关紧要,对吧?
    • 我对 Windows 了解不多,但这是我能想到的。这一切都与 Windows 创建新进程的方式有关(80 年代早期的设计决策方式):它们将 forkexecvp 合并为一个函数,因此您无法在子进程开始之前修改文件描述符运行新进程。另外,我不确定 Windows 如何处理管道(或者是否有管道)。
    【解决方案4】:

    首先,您是否只需要想让您的原始代码可重用?在这种情况下,您可以将其构建为库并将其链接到您的新应用程序中。

    如果您真的想与另一个可执行文件进行通信,那么您可以需要将其作为主应用程序的子进程启动。我会推荐Poco C++ librariesProcess 类。

    【讨论】:

      【解决方案5】:

      看起来像是 popen() 的工作,在 Linux、WindowsOS X 上可用

      【讨论】:

      • popen 似乎是 *nix 特有的,而不是语言特有的 - 还是我弄错了?
      • @sparkFinder:(假设“特定语言”是指“标准库的一部分”)我不认为进程生成和流重定向是标准 C++ 的一部分。但是 popen 并不完全是 unix 特有的,因为它也可以在 Windows 上使用。
      【解决方案6】:

      听起来您只打算在可执行级别进行功能测试。这还不够。如果您打算进行彻底的测试,您还应该编写单元测试。为此,有一些优秀的框架。 (到目前为止)我最喜欢的 C++ 是 BOOST::Testing。

      如果您控制源代码,除了从外部进程启动 exe 外,还有一些常见的功能测试技巧:嵌入功能测试。您只需在程序中添加一个执行测试的选项。这很酷,因为测试嵌入在代码中,并且可以在任何执行环境中轻松启动自动检查。

      这意味着在测试环境中,当您使用一些测试专用参数调用程序时,没有什么可以阻止您完全完成并重定向 stdout 的内容,甚至从程序中检查测试结果。这将使整个测试比从外部启动器调用更容易,然后从启动器分析结果。

      【讨论】:

      • 我现在需要的测试级别是功能级别。我们没有太多要测试的类,只有一些核心功能。
      • 不要误会我的意思。当你有很多类要测试时,单元测试不是你要做的事情。越少越好。如果你只有一些核心功能要测试,单元测试更适合。我仍然想知道您打算通过启动 exe 来测试什么。这类自动化测试通常很难编写,运行 exe 是最简单的步骤。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 2013-06-26
      • 2017-03-24
      • 1970-01-01
      相关资源
      最近更新 更多