Dima1982
Dima1982

Reputation: 109

Improper use of system() call?

I have a particle system program that generates a .dat file with particle coordinates in every iteration. The end goal is to run the program multiple times via a script with different parameters. So, I am trying to setup my program in a way that, for every run, all relevant data are going to be stored in a folder.

What I do is to generate PNGs from the .dat files with Gnuplot, call ffmpeg to create a video out of the PNGs, use WinRAR to compress the .dat files and finally clean up, by deleting all the intermediate files. This works, when I do it in the working directory.

Now I try to create a new directory and do the same stuff in there. My code:

// Load the proper library to use chdir() function
#ifdef _WIN32
#include <direct.h>
#elif defined __linux__ || defined __APPLE__&&__MACH__
#include <unistd.h>
#endif

// Make output directory and change working directory to new directory
    ostringstream dirCommand;
    dirCommand << "mkdir " << folderName_str;
    system(dirCommand.str().c_str());
    const char* test  = folderName_str.c_str();
    #ifdef _WIN32
        if(_chdir(test))
        {
            printf( "Unable to locate the directory: %s\n",test);
            return;
        }
    #elif defined __linux__ || defined __APPLE__&&__MACH__
        if(chdir(test))
        {
            printf( "Unable to locate the directory: %s\n",test);
            return;
        }
    #endif
        else
            printf("Created output directory...\n");

Already for this part, I know that there are going to be objections. I have looked extensively on SO and many people favor SetCurrentDirectory() for Windows, or they are skeptical about using system(). In my defense, I am a novice programmer and my knowledge is really limited...

Now, when I try to make the video with FFMpeg and then rar/tar my files:

// Make video
        std::cout << "Generating Video..." << endl;
        ostringstream command;
        command << "ffmpeg -f image2 -r 1/0.1 -i output_%01d.png -vcodec mpeg4 " << videoName_str << ".avi -loglevel quiet";
        std::system(command.str().c_str());

        // Clean Up!
        std::cout << "Cleaning up!" << endl;
        ostringstream command2;
        #ifdef _WIN32
            command2 << "rar -inul a " << videoName_str << ".rar *.dat settings.gp loadfile.gp";
        #elif defined __linux__ || defined __APPLE__&&__MACH__
            command2 << "tar cf " << videoName_str << ".tar *.dat settings.gp loadfile.gp";
        #endif
        std::system(command2.str().c_str());

I get very different behaviors in Win/ Linux.

Win 7 x64, Visual Studio 2010/12

In windows, the folder is created. The .dat files are generated correctly and gnuplot plots the PNGs as well. When ffmpeg is called, nothing happens. No error message from FFMpeg or anything. The same goes for WinRAR. Maybe, for the last thing, I can use the command line utility of 7z which is free!

Linux Mint 14 x64, Qt 4.8.1

Strangely enough, the behavior is inverted from that of Windows. As soon as the dir is changed, only the first .dat file is generated. It is as if every subsequent call I make to fprintf() for my file generation does not work, or gets lost somewhere. Gnuplot works, as do ffmpeg and tar!!

I am really perplexed. Any help, would be really appreciated.

Upvotes: 0

Views: 255

Answers (1)

DanielKO
DanielKO

Reputation: 4517

A few points that might be helpful:

  1. Make sure to check the result of every system call, including system() and fprintf().

  2. It's been a while since I last touched Windows; I remember that depending on how binaries were linked, they would not always print out to the same console. So ffmpeg/winrar could be throwing the error messages away, or just allocating a new, short-lived console to print.

  3. I would use mkdir/_mkdir instead of calling system().

  4. With popen()/_popen() you can get more control over the error output.

  5. Consider using a shell script or bat file.

Upvotes: 1

Related Questions