【问题标题】:Substitute for call to "system" in my C++ program在我的 C++ 程序中替换对“系统”的调用
【发布时间】:2014-04-12 16:48:44
【问题描述】:

我正在尝试在我的 C++ 程序中找到对 "system"(来自 stdlib.h)的调用的替代方法。 到目前为止,我一直在使用它在我的程序中调用 g++ 进行编译,然后在用户选择的目录中链接可变数量的源文件。

这里我有一个示例,该命令大致如下所示:"C:/mingw32/bin/g++.exe -L"C:\mingw32\lib" [...]"

但是,我遇到的问题是(至少对于我正在使用的 MinGW 编译器)我在执行命令时收到错误 “命令行太长”字符串太长。 就我而言,它大约有 12000 个字符长。所以我可能需要另一种方式来调用 g++。 此外,我了解到您通常无论如何都不应该使用“系统”http://www.cplusplus.com/forum/articles/11153/

所以我需要一些替代品(它也应该尽可能独立于平台,因为我希望程序可以在 Windows 和 Linux 上运行)。 我找到了一位通常看起来非常适合的候选人:

  • _execv / execv

    独立于平台,但是:

    a) http://linux.die.net/man/3/exec 说“exec() 系列函数用新的进程映像替换当前进程映像”。那么我是否需要先调用 "fork" 以使 C++ 程序不被终止? Windows/MSVC 上也可以使用 fork 吗?

    b) 使用“system”,我测试了返回值是否为0,看看是否可以编译源文件。这将如何与 exec 一起工作?如果我正确理解手册页,它只会返回创建新进程的成功而不是 g++ 的状态吗?我可以使用哪个函数暂停我的程序以等待 g++ 完成并获取返回值?

总而言之,我不太确定我应该如何处理这个问题。你有什么建议? Java (Runtime.getRuntime().exec(command)) 或 Eclipse C++ IDE 等多平台程序如何在内部解决这个问题?您建议我如何以独立于系统的方式调用 g++ - 使用尽可能多的参数?

编辑: 现在我正在使用以下代码 - 我只在 Windows 上测试过它,但至少在那里它似乎按预期工作。谢谢你的想法,jxh! 也许我将来会考虑通过使用相对路径来缩短命令。然后我必须找到一种独立于平台的方法来更改新进程的工作目录。

#ifdef WIN32
int success = spawnv(P_WAIT, sCompiler.c_str(), argv);
#else
pid_t pid;
switch (pid = fork()) {
case -1:
    cerr << "Error using fork()" << endl;
    return -1;
    break;
case 0:
    execv(sCompiler.c_str(), argv);
    break;
default:
    int status;
    if (wait(&status) != pid) {
        cerr << "Error using wait()" << endl;
        return -1;
    }
    int success = WEXITSTATUS(status);
}
#endif

【问题讨论】:

  • fork() 适用于支持该调用的 POSIX 系统,而 MINGW 不为 Windows 实现它。应该有一个&lt;process.h&gt; 头文件提供spawn*(),这是MINGW 替代fork()/exec() 调用。
  • 我不敢问为什么您需要超过 12,000 个字符的命令行。我读过篇幅较少的短篇小说。
  • 该命令的问题在于它包含每个文件的源目录路径(例如“C:/Users/Christoph/C++-Projekte/GameProgramming/LandsOfShadow/leveleditor_interface/Audio/Audio .o”)。有数百个源文件,这会变得很长......
  • 你能解析出重复的部分,或者至少设置更短的符号链接到目录吗?
  • 因为所有源文件都有相同的父文件夹,我可以通过将 g++ 的工作目录更改为源目录来缩短它们,然后只使用“main.o”等相对文件路径而不是绝对路径,例如“C:/Users/Christoph/C++-Projekte/GameProgramming/LandsOfShadow/leveleditor_interface/main.cpp”。但是,我不确定如何设置 g++ 进程的工作目录。

标签: c++ c process cross-platform exec


【解决方案1】:

如果您的所有文件都位于(或可以移动到)一个(或少数)目录中,您可能会使用其中一些命令行选项获得一些牵引力。给定您到 audio.o 的示例路径,这将使您的命令行减少约 90%。

-Ldir
Add directory dir to the list of directories to be searched for `-l'.

发件人:https://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html#SEC17

-llibrary
Search the library named library when linking.

在命令的哪个位置编写此选项会有所不同;链接器按照指定的顺序搜索进程库和目标文件。因此,foo.o -lz bar.o' searches libraryz' 在文件 foo.o' but beforebar.o' 之后。如果bar.o' refers to functions inz',则可能无法加载这些函数。

链接器搜索库的标准目录列表,该库实际上是一个名为“liblibrary.a”的文件。链接器然后使用这个文件,就好像它是通过名称精确指定的一样。

搜索的目录包括几个标准系统目录以及您使用 `-L' 指定的任何目录。

通常以这种方式找到的文件是库文件——其成员是目标文件的存档文件。链接器通过扫描归档文件来处理归档文件,其中的成员定义了迄今为止已被引用但尚未定义的符号。但是如果找到的文件是一个普通的目标文件,它会以通常的方式链接。使用 -l' option and specifying a file name is that-l' 与 lib' and.a' 包围库并搜索多个目录之间的唯一区别。

发件人:http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html

【讨论】:

  • 这似乎是最好的解决方案,因为它是可移植的,您不需要添加任何操作系统特定的代码。谢谢你的回答!
  • 我将您的答案标记为最有帮助的解决方案,但是,我无法投票,因为我还没有“15 声望”。
【解决方案2】:

这是另一种选择,可能更接近您的需要。在调用 system() 之前尝试更改目录。例如,这就是 Ruby 中发生的事情……我猜它在 C++ 中的作用是一样的。

> system('pwd')
/Users/dhempy/cm/acts_rateable
=> true
> Dir.chdir('..')
=> 0
> system('pwd')
/Users/dhempy/cm
=> true

【讨论】:

    【解决方案3】:

    如果其他答案都没有,那就是另一个答案。您可以将环境变量设置为目录的路径,然后在您链接的每个文件之前使用该变量。

    我不太喜欢这种方法,因为您必须修改环境,而且我不知道这是否真的会影响命令行限制。可能是在插入命令后应用限制。但是,无论如何,有一些事情要做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      • 2016-01-13
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      相关资源
      最近更新 更多