在我的C ++程序中替换为“system”的调用

时间:2014-04-12 16:48:44

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

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

这里我举了一个例子,命令大致如下:" C:/ mingw32 / bin / g ++。exe -L" C:\ mingw32 \ lib" [...]"

但是,我遇到的问题是(至少使用 MinGW编译器我正在使用)我收到错误"命令行太长" 当命令字符串太长时。 就我而言,它长约12000个字符。所以我可能需要另一种方法来调用g ++。 另外,我读过你一般不应该使用" system"无论如何http://www.cplusplus.com/forum/articles/11153/

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

  • _execv / execv

    平台独立,但是:

    a)http://linux.die.net/man/3/exec说" exec()系列函数用新的过程映像替换当前过程映像"。所以我需要首先调用" fork" ,以便C ++程序不会被终止? fork是否也可用于 Windows / MSVC

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

总而言之,我不太清楚应该如何处理这个问题。你有什么建议?多个平台程序如 Java (Runtime.getRuntime()。exec(命令))或 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

3 个答案:

答案 0 :(得分:0)

如果您的所有文件都在(或可以移动到)一个(或少量)目录中,您可能会对这些命令行选项有所了解。给定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 library bar.o'之后的foo.o' but before z'。如果bar.o' refers to functions in z',则可能无法加载这些函数。

链接器搜索库的标准目录列表,实际上是一个名为`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

答案 1 :(得分:0)

这是另一种选择,也许更接近你需要的选择。尝试在调用system()之前更改目录。例如,这里发生在Ruby中的情况......我猜测它在C ++中的行为是一样的。

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

答案 2 :(得分:0)

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

我不太喜欢这种方法,因为你必须修补环境,我不知道这是否会影响命令行限制。可能是在插入命令后应用限制。但是,无论如何都要有所作为。