Call a Matlab function from c++ - c++

I have a small code snippet that calls a matlab function (saved in its own .m file). The user can choose the matlab function to call and it may or may not be in MATLAB's default folder (~/Documents/MATLAB).
In the event that it's not in the default search path, I would like to add the function's containing folder to MATLAB's search path. When I try to do this using the Terminal (I am on a MAC), with this command:
/Applications/MATLAB_R2011b.app/bin/matlab -r "addpath(genpath('/Folder/Address/Here'))"
MATLAB launches, and I can see that the new address was successfully added to the search path.
However, when I try to run this command through the C++ program using this:
std::string matlabFunctionPath = "/Folder/Address/Here"
std::string addPathCommand = "/Applications/MATLAB_R2011b.app/bin/matlab -r \"addpath(genpath('"+ matlabFunctionPath + "')\"";
::popen(shellCommand.c_str(), "r"));
MATLAB does launch but the new address does not get added to the search path. What am I doing wrong here?
I appreciate the help.

You are missing the second closing )
std::string addPathCommand = "/Applications/MATLAB_R2011b.app/bin/matlab -r \"addpath(genpath('"+ matlabFunctionPath + "'))\"";

Related

How Matlab knows there is a .mex64 file and avoid infinity "compiling" loop

I created a MyMex.m and a MyMex.cpp. Inside the .m I compile the .cpp using mex. It should happen only if the .mex64 does not exists. The .mex64 is complite to a directory in Matlab PATH. But Matlab will keep running the .m on an infinity loop if I don't set the Matlab current working dir to the .mex64 dir. What I'm missing?
MyMex.m:
function [dataOut] = MyMex(dataIn)
mexCppFile = 'MyMex.cpp';
mexCmd = 'mex MyMex.cpp;';
fprintf('\nFile %s not compiled yet, compiling it now...\n%s\n',mexCppFile,mexCmd);
fileFullPath = which(mexCppFile);
if size(fileFullPath,2) > 0 && exist(fileFullPath,'file')
[fileDir, fileName, ext] = fileparts(fileFullPath);
curDir = pwd;
cd(fileDir);
mex MyMex.cpp;
cd(curDir);
else
error('prog:input','Unable to find %s to compile it. Check if the file is in the current dir or in the Matlab PATH!',mexCppFile);
end
% Call C++ mex
[dataOut] = MyMex(dataIn)
end
Edit to defend myself from the comments that I did a infinity loop:
Matlab was supposed to know that there is a compiled version of the function. I don't know how it does it and my problem is related to that, since some times it finds the function some times it doesn't.
Here is a consolidated online mex sample that does the same "infinity" thing and work smoothly:
2D interpolation
His code in mirt2D_mexinterp.m:
% The function below compiles the mirt2D_mexinterp.cpp file if you haven't done it yet.
% It will be executed only once at the very first run.
function Output_images = mirt2D_mexinterp(Input_images, XI,YI)
pathtofile=which('mirt2D_mexinterp.cpp');
pathstr = fileparts(pathtofile);
mex(pathtofile,'-outdir',pathstr);
Output_images = mirt2D_mexinterp(Input_images, XI,YI);
end
Maybe the .m and the .mex64 need to be on the same folder.
It all comes down to Matlab's search path.
Mex-files are prioritized over m-files if they are on the same level in the path. And files in the current directory take precedence over files found elsewhere in the matlab search path.
So when you experience an infinite loop, it is clear that the m-file is locate higher in the search path than the mex-file.
In essence, all is fine if the two files are in the same folder.

How can I find why system can not run my application?

I have a c++ program that run a command and pass some arguments to it. The code is as follow:
int RunApplication(fs::path applicationPathName,std::string arguments)
{
std::string applicationShortPath=GetShortFileName(applicationPathName);
std::string cmd="\""+applicationShortPath +"\" "+ arguments+" >>log.txt 2>&1 \"";
std::cout<<cmd<<std::endl;
int result=std::system(cmd.c_str());
return result;
}
When I run system command, the cmd window appears shortly and then closes, but the result is 1 and the cmd was not run (the command should generate output which is not generated).
To check that the cmd is correct, I stopped the application just before system line and copy/ paste cmd content to a cmd window and it worked.
I am wondering how can I find why application is not run in system()?
the cmd has this value just before running it:
"D:/DEVELO~3/x64/Debug/enfuse.exe" -w --hard-mask --exposure-weight=1 --saturation-weight=0.328 --contrast-weight=0.164 -o "C:/Users/m/AppData/Local/Temp/1.tif" "C:/Users/m/AppData/Local/Temp/1.jpg" "C:/Users/m/AppData/Local/Temp/2.jpg" >>log.txt 2>&1 "
How can I find why it is not working?
Is there any way that I set the system so it doesn't close cmd window so I can inspect it?
is there any better way to run a command on OS?
Does Boost has any solution for this?
Edit
After running it with cmd /k, I get this error message:
The input line is too long.
How can I fix it other than reducing cmd line?
There are two different things here: if you have to start a suprocess, "system" is not the best way of doing it (better to use the proper API, like CreateProcess, or a multiplatform wrapper, but avoid to go through the command interpreter, to avoid to open to potential malware injection).
But in this case system() is probably the right way to go since you in fact need the command interpreter (you cannot manage things like >>log.txt 2>&1 with only a process creation.)
The problem looks like a failure in the called program: may be the path is not correct or some of the files it has to work with are not existent or accessible with appropriate-permission and so on.
One of the firt thing to do: open a command prompt and paste the string you posted, in there. Does it run? Does it say something about any error?
Another thing to check is how escape sequence are used in C++ literals: to get a '\', you need '\\' since the first is the escape for the second (like \n, or \t etc.). Although it seems not the case, here, it is one of the most common mistakes.
Use cmd /k to keep the terminal: http://ss64.com/nt/cmd.html
Or just spawn cmd.exe instead and inspect the environment, permissions, etc. You can manually paste that command to see whether it would work from that shell. If it does, you know that paths, permssions and environment are ok, so you have some other issue on your hands (argument escaping, character encoding issues)
Check here How to execute a command and get output of command within C++ using POSIX?
Boost.Process is not official yet http://www.highscore.de/boost/process/

Lua loadfile() cannot find file in same directory

Odd problem here.
I have a Lua script ('human.lua') that is executed through dofile() in a C++ application.
I attempt to load another file which is an AI script in a pretty standard way on the first line:
behavior_chunk = assert(loadfile("testBehavior.lua"))
This throws 'cannot open testBehavior.lua: no such file or directory".
testBehavior.lua is in the same dir as human.lua.
How is this happening?
Could package.path be getting set erroneously somehow?
I have done a lot of research on this and cannot find what may be causing this specific problem.
Maybe I'm missing something really obvious.
The loadfile path is relative to working directory, not relative to script location. So if you started Lua from folder A to run B\human.lua, then loadfile("C/testBehavior.lua") from human.lua looks for testBehavior.lua in A/C, not in B/C.
So if your folder structure is:
Foo
yourLuaApp.exe
Scripts
human.lua
file1.lua
file2.lua
ai
testBehavior.lua
and say you have C++
int main(argc, char* argv[])
{
... init Lua ...
std::string fullname = "scripts/" + argv[1];
if (luaL_dofile(pLua, fullname.c_str()))
std::cerr << "error" << endl;
else
std::cout << "success" << endl;
}
then you will get these results:
C:\Foo> yourLuaApp.exe file1.lua
success
C:\Foo> yourLuaApp.exe ai\testBehavior.lua
success
but
C:\Foo\Scripts> ../yourLuaApp.exe file1.lua
error
because you are starting your app from Scripts folder, which does not contain a folder called Scripts.
Thanks for the update.
However loading the script in C++ works flawlessly, the problem comes in when I load a Lua script from WITHIN that Lua script I loaded from C++:
behavior_chunk = assert(loadfile("testBehavior.lua"))
How would I correctly use loadfile from inside a Lua script (not C++) to load another Lua file in the same directory, or in a sub-directory?
My reasoning is that I loaded 'human.lua' from the 'scripts' dir in C++. Now inside 'human.lua' I load another script that is located in the same directory as that script, so why wouldn't that work?
Maybe I didn't make this clear enough. I apologize if that's the case.

Problems passing source command to bash from c++ application

I am developing an application for work that allows the users to quickly set environment variables on a terminal basis. By setting the path in each terminal we ensure files with the same name in different directories aren't causing application testing to be problematic. I am Using Qt to build the program which is c++ based and all the datatypes are foundationally the same.
I am using the following code to invoke commands in the terminal from which the application launches from using system(). I can run commands into the bash just fine with code; however, I run into a problem when I attempt to use a command with arguments. This is probably why source doesn't seem to work right as the source command is followed by the filename. It would appear that I drop the argument appended after the bash command.
My Code:
void assignTerminalToPath(QString path)
{
QString data = "";
QString currentUsersHomeDirectory = QDir::homePath();
QString tmpScriptLocation = currentUsersHomeDirectory;
QByteArray ba;
tmpScriptLocation += "/.tmpSourceFile";
QFile tmpSourceFile(tmpScriptLocation);
if(tmpSourceFile.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream output(&tmpSourceFile);
data.append("export PATH=.:");
data.append(path);
data.append(":$PATH");
output << QString("#!/bin/bash\n");
output << data;
tmpSourceFile.close();
}
data.clear();
data.append("/bin/bash -c source ");
data.append(tmpScriptLocation);
ba = data.toLatin1();
const char *cStr = ba.data();
system(cStr);
}
Perhaps I'm not referencing bash correctly and I need something outside of -c?
Reference Execute shell/bash command using C/C++
Thanks for any help in advance!
source is not a program that you can call, it is embedded bash command. It is designed to be processed by bash without invoking another copy of bash, such that environment variables can be changed in current bash copy.
However, you cannot call source as part of system(). And even if you did succeed at that, its effects to change environment variables would be completely lost for caller app once system() has returned.
Try a command to envelop with parameters in double quotes ("command - arg1 - to arg2") to transfer in the function system().
used:
char *com = "\"command -arg1 -arg2\"";
system(com);

Executing a command from C++, What is expected in argv[0]?

I am using execv() to run commands from /bin/ such as 'ls', 'pwd', 'echo' from my c++ program, and I am wondering what value I should provide in argv[0];
const char * path = getPath();
char ** argv = getArgs();
execv(path,argv);
argv[0] is supposed to be the program name. It's passed to the program's main function. Some programs differentiate their behavior depending on what string argv[0] is. For example the GNU bash shell will disable some of its features if called using sh instead of bash. Best give it the same value that you pass to path.
In linux, argv[0] is the process name displayed by the top utility (which it probably gets from reading entries in /proc/)
argv[0] should be the full path of the command that you want to run.
I know that this is not the answer you're looking for but is there a specific reason why you're doing this? The reason I ask is that most if not all of the actions people normally run with either system() or execv() are available in libraries on either Windows or Unix and are safer, faster and less likely to suffer from circumstantial errors. By that I mean, for example, when the PATH changes and suddenly your code stops working.
If you're passing in a string, either in whole or in part, and running it then you also leave yourself open to a user gaining access to the system by entering a command that could be damaging. E.g. imagine you've implemented a file search using find /home -name and your user types in:
"%" -exec rm {} \;
Ouch!