简体   繁体   English

在我的C ++程序中代替对“系统”的调用

[英]Substitute for call to “system” in my C++ program

I'm trying to find find a substitute for a call to "system" (from stdlib.h) in my C++ program. 我试图在我的C ++程序中找到对“系统” (来自stdlib.h)的调用的替代方法。 So far I've been using it to call g++ in my program to compile and then link a variable number of source files in a directory chosen by the user. 到目前为止,我一直在使用它在程序中调用g ++进行编译,然后将可变数量的源文件链接到用户选择的目录中。

Here I've got an example how the command could approximately look like: "C:/mingw32/bin/g++.exe -L"C:\\mingw32\\lib" [...]" 在这里,我有一个示例,命令大致如下所示:“ C:/ mingw32 / bin / g ++。exe -L” C:\\ mingw32 \\ lib“ [...]”

However, I have the problem that (at least with the MinGW compiler I'm using) I get the error "Command line is too long" when the command string gets too long. 但是,我遇到的问题是(至少在我使用的MinGW编译器中 )当命令字符串太长时出现错误“命令行太长” In my case it was about 12000 characters long. 以我为例,它的长度约为12000个字符。 So I probably need another way to call g++. 所以我可能需要另一种方式来调用g ++。 Additionally, I've read that you generally shouldn't use "system" anyway : http://www.cplusplus.com/forum/articles/11153/ 另外,我读到您通常不应该使用“系统”http : //www.cplusplus.com/forum/articles/11153/

So I'm in need for some substitute (that should also be as platform independent as possible, because I want the program to run on Windows and Linux). 因此,我需要一些替代方法(也应该尽可能与平台无关,因为我希望程序可以在Windows和Linux上运行)。 I've found one candidates that would generally look quite well suited: 我发现一个通常看起来非常合适的候选人:

  • _execv / execv : _execv / execv

    Platform independent, but: 平台无关,但:

    a) http://linux.die.net/man/3/exec says "The exec() family of functions replaces the current process image with a new process image". a) http://linux.die.net/man/3/exec表示“ exec()系列函数新的过程映像替换为当前过程映像”。 So do I need to call "fork" first so that the C++ program isn't terminated? 那么,我是否需要先调用“ fork”,以便C ++程序不会终止? Is fork also available on Windows/MSVC ? Windows / MSVC上也可以使用fork吗?

    b) Using "system", I've tested whether the return value was 0 to see if the source file could be compiled. b)使用“系统”,我测试了返回值是否为0,以查看是否可以编译源文件。 How would this work with exec? 与exec如何配合使用? If I understand the manpage correctly, will it only return the success of creating the new process and not the status of g++? 如果我正确理解了手册页,它只会返回创建新进程的成功信息,而不返回g ++的状态吗? And with which function could I suspend my program to wait for g++ to finish and get the return value? 我可以使用哪个函数挂起程序以等待g ++完成并获取返回值?

All in all, I'm not quite sure how I should handle this. 总而言之,我不太确定该如何处理。 What are your suggestions? 您有什么建议? How do multiplatform programs like Java (Runtime.getRuntime().exec(command)) or the Eclipse C++ IDE internally solve this? Java (Runtime.getRuntime()。exec(command))或Eclipse C ++ IDE等多平台程序如何在内部解决此问题? What would you suggest me to do to call g++ in an system independent way - with as many arguments as I want? 您会建议我做什么,以一种与系统无关的方式调用g ++-我需要多少个参数?

EDIT: Now I'm using the following code - I've only tested it on Windows yet, but at least there it seems to work as expected. 编辑:现在我正在使用以下代码-我仅在Windows上对其进行了测试,但至少在这里它能按预期工作。 Thanks for your idea, jxh! 谢谢您的想法,jxh! Maybe I'll look into shortening the commands by using relative paths in the future. 也许将来我会考虑通过使用相对路径来缩短命令。 Then I would have to find a platform independent way of changing the working directory of the new process. 然后,我将不得不找到一种与平台无关的方式来更改新进程的工作目录。

#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

You might get some traction with some of these command line options if all your files are in (or could be moved to) one (or a small number) of directories. 如果所有文件都位于(或可以移至)一个(或少量)目录中,那么使用某些命令行选项可能会有所帮助。 Given your sample path to audio.o, this would reduce your command line by about 90%. 给定您到audio.o的示例路径,这将使您的命令行减少大约90%。

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

From: https://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html#SEC17 来自: https : //gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html#SEC17

-llibrary
Search the library named library when linking.

It makes a difference where in the command you write this option; 在命令中写入此选项的位置会有所不同。 the linker searches processes libraries and object files in the order they are specified. 链接器按指定的顺序搜索过程库和目标文件。 Thus, foo.o -lz bar.o' searches library z' after file foo.o' but before bar.o'. 因此, foo.o -lz bar.o' searches library '在文件foo.o' but before foo.o -lz bar.o' searches library z'。 If bar.o' refers to functions in z', those functions may not be loaded. 如果bar.o' refers to functions in z'中的函数,则可能不会加载这些函数。

The linker searches a standard list of directories for the library, which is actually a file named `liblibrary.a'. 链接器在标准目录列表中搜索该库,该库实际上是一个名为“ liblibrary.a”的文件。 The linker then uses this file as if it had been specified precisely by name. 链接器然后使用该文件,就好像它是通过名称精确指定的一样。

The directories searched include several standard system directories plus any that you specify with `-L'. 搜索的目录包括几个标准系统目录以及您用`-L'指定的目录。

Normally the files found this way are library files--archive files whose members are object files. 通常,以这种方式找到的文件是库文件-归档文件,其成员是目标文件。 The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. 链接器通过扫描存档文件来查找成员,这些成员定义了到目前为止已被引用但尚未定义的符号。 But if the file that is found is an ordinary object file, it is linked in the usual fashion. 但是,如果找到的文件是普通的目标文件,则以通常的方式链接。 The only difference between using an -l' option and specifying a file name is that -l' surrounds library with lib' and .a' and searches several directories. 使用-l' option and specifying a file name is that之间的唯一区别-l' option and specifying a file name is that -l'用lib' and .a'包围库并搜索多个目录。

From: http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html 来自: http : //gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html

Here's another option, perhaps closer to what you need. 这是另一个选择,也许更接近您的需求。 Try changing the directory before calling system(). 尝试在调用system()之前更改目录。 For example, here's what happens in Ruby...I'm guessing it would act the same in C++. 例如,这就是Ruby中发生的事情……我猜想它在C ++中的作用相同。

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

If none of the other answers pan out, here's another. 如果没有其他答案可以解决,那么这里是另一个。 You could set an environment variable to be the path to the directory, then use that variable before each file that you link in. 您可以将环境变量设置为目录的路径,然后在链接到的每个文件之前使用该变量。

I don't like this approach much, as you have to tinker with the environment, and I don't know if that would actually affect the command line limit. 我不太喜欢这种方法,因为您必须修改环境,而且我不知道这是否会真正影响命令行限制。 It may be that the limit applies after interpolating the command. 插值命令后可能会应用该限制。 But, something to thing about, regardless. 但是,无论如何,都有些事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM