Search code examples
c++windowsmatlablaunching-application

Launching matlab script from C++ and wait for result


Following a few posts on StackOverflow, I'm launching a matlab script by running

matlab.exe -nodisplay -nosplash -nodesktop -r "run('script.m'); exit;"

Actually, since this script requires parameters, I also set them as global variables. It works well. However, I am running this script multiple times passing different parameters, and I wanted for an instance of the script to finish before launching the next instance.

So, in my C++ code, I am doing:

        SHELLEXECUTEINFO ShExecInfo = { 0 };
        ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
        ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
        ShExecInfo.hwnd = NULL;
        ShExecInfo.lpVerb = NULL;
        ShExecInfo.lpFile = _T("matlab.exe");
        ShExecInfo.lpParameters = _T("-nodisplay -nosplash -nodesktop -r \"file1='tmp0.png'; file2='tmp1.png'; outfile='tmpout.flo'; run('runflow.m'); exit; \"");
        ShExecInfo.lpDirectory = NULL;
        ShExecInfo.nShow = SW_SHOWMINNOACTIVE;
        ShExecInfo.hInstApp = NULL;
        ShellExecuteEx(&ShExecInfo);
        WaitForSingleObject(ShExecInfo.hProcess, INFINITE);

This actually doesn't wait for the script to finish, and I end up with hundreds of simultaneous matlab instances. To avoid that, I just did a small hack: to delete the file tmp0.png from matlab, and wait for this file to be removed:

        SHELLEXECUTEINFO ShExecInfo = { 0 };
        ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
        ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
        ShExecInfo.hwnd = NULL;
        ShExecInfo.lpVerb = NULL;
        ShExecInfo.lpFile = _T("matlab.exe");
        ShExecInfo.lpParameters = _T("-nodisplay -nosplash -nodesktop -r \"file1='tmp0.png'; file2='tmp1.png'; outfile='tmpout.flo'; run('runflow.m'); delete('tmp0.png'); exit; \"");
        ShExecInfo.lpDirectory = NULL;
        ShExecInfo.nShow = SW_SHOWMINNOACTIVE;
        ShExecInfo.hInstApp = NULL;
        ShellExecuteEx(&ShExecInfo);
        WaitForSingleObject(ShExecInfo.hProcess, INFINITE);

        while (file_exists("tmp0.png")) ;  

where:

bool file_exists(const char* filename) {
    std::ifstream ifile(filename);
    return ifile.good();
}

But this sometimes works, and sometimes not. In particular, it often runs into an infinite loop.... until I manually go to the windows explorer, right click on the file 'tmp0.png' and click 'Properties', at which point, it realizes the files might have been removed and finally engages to the next iteration...

[EDIT] Actually, I realize that /each time/ I click on Properties, it launches a new Matlab instance, whether there is already an instance running or not...

1) Why is this happening ?
2) How can I circumvent that (I am not particularly looking for elegant solutions ; just something that works).
3) I would further like to launch a few such instances in parallel...

Thanks!


Solution

  • Opening a file in a tight loop may not give a chance for the OS to consider deleting it; consider If you own the file whilst the OS executes the delete call initiated by Matlab.

    Adding a sleep or a wait (of atleast 100ms, more the better) in the loop should give time for the operating system to delete the file.