在我的C++程序中替代呼叫"system"

Substitute for call to "system" in my C++ program

本文关键字:呼叫 system 我的 C++ 程序      更新时间:2023-10-16

我正试图在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().exc(命令))或EclipseC++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

如果您的所有文件都在(或可以移动到)一个(或少量)目录中,那么使用这些命令行选项可能会获得一些吸引力。给定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' but before bar.o之后为foo.o -lz bar.o' searches library 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

这里有另一个选项,也许更接近您的需求。在调用system()之前,请尝试更改目录。例如,以下是Ruby中发生的情况。。。我猜它在C++中的作用也是一样的。

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

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

我不太喜欢这种方法,因为你必须修改环境,我不知道这是否真的会影响命令行限制。这可能是在对命令进行插值之后应用的限制。但是,无论如何,有些事情值得关注。