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.
Related
I have a very weird problem. The setup is the following:
Library A uses Library B
Both libraries are installed as shared library independently and A links to B using CMake packages.
When I create an executable that directly links to B, everything works fine.
When I create an executable that links to A however, which is using B, then for some reason my fstream in B fails to open a specific file. I am 100% certain the file exists, is not requiring authorization and is not currently used. The error thrown by strerror(errno) is "No such file or directory".
I really have no clue what might go wrong. This is the code snippet I use for opening:
ifstream f;
f.open(filename.c_str(), ios_base::in|ios::binary);
if (f.fail()) {
std::cout << "Opening Vocabulary failed: " << std::strerror(errno) << std::endl;
return false;
}
I triple checked the path in filename is correct. These are the last resorts I can think of:
Maybe Library A uses another C++ Standard as B, which is why the call to fstream fails?
Maybe filename string is somehow corrupted, even though the path seems to be correct?
Maybe some memory leak corrupts my c_str() command?
Is there anything else that I could check?
Edit: Ah, one thing I forgot: The fstream command is in a templated function in a header file. Maybe this has something to do with it?
Edit2: Here is the stack trace. "ORBVoc.bin" is the file I wanted to open. The only information I get out of this is, it does not exist...though it does exist.
https://www.file-upload.net/download-14359408/strace.log.html
Okay, apparently a reboot was all it takes. Today everything works flawlessly. No permissions, file or line of code was changed. I assume either something went terribly wrong, when my Laptop came back from hibernation. Or it was some pending ubuntu update? I really have no idea. I could swear it was shutdown at least once the past 2-3 days. But jeah, I have no other explanation. Maybe someone smarter can answer this with his glass ball...
Anyway, thanks for the answers, appreciate it! At least I learned about strace $:^)
Is there any good way i can make some data created by my c++ program available to the shell after exiting the program?
I have a c++ program, inside which i have a string containing a path:
std::string path = "/home/some/path"
I want this path to be available after the c++ program exits main and i am returned to the shell, so that i can use that path (e.g. cd to that path).
I have considered/tried the following approaches:
I tried making an environment variable in c++ program using setenv(). However the environment variable only exists while in the c++ program, and it is apparently not possible to make those changes visible in the shell after exiting the program.
(considered) writing the path to a temporary file, so that a bash script could later access the details of the path from it. However i have read many suggestions to not do that due to security vulnerabilities.
I tried calling the bash script from within the c++ program, using system(). This does not work if i try to cd to that directory (exiting the program will keep me in the same directory as before).
I figure that if i am desperate, i could have my program cout the path, and use the solutions as described here:
$ ./program | tee output.txt
Then the path is stored inside the file. This works technically, but has the undesirable effect of creating a file and printing the path to the screen, and is basically creating a temporary file.
another option to, again, cout in my program, and use command substitution. running in the shell
$ var=$(./program)
storing the path in var. This didnt work because my program does many things including requiring user input before calling
std::cout<< path << std::endl;.
Particularly, i have observed this approach to not display a curses window, which is required for the program.
the only solution that has worked is piping the output to tee.
Environment variables are only an input, they cannot be used to return any information from a program.
You are already using std::cin and std::cout for user input, and std::cerr should be reserved for error messages. However, you can have the shell open more filedescriptors, and have your program write to those. However, doing this with pure C++ is not possible. But if you don't mind using POSIX C functions:
#include <cstdio>
int main() {
FILE *f = fdopen(3, "w");
fprintf(f, "some path\n");
}
And then use it like so:
./program 3> output.txt
This of course creates an undesirable file. I don't think there is any way to store the output from an extra filedescriptor directly to a variable in bash. However, you could create a temporary file inside /dev/shm, so it will never be written to disk, or create a FIFO object and redirect the output from the program to the FIFO, and then read it back. For some examples of how to do this, see this question.
You could write the output that you want the user to see to stderr instead of stdout. Only output what you need your shell script to see to stdout:
#include <iostream>
int main() {
std::clog << "Enter data: "; // clog prints to stderr like cerr
std::string line;
std::getline(std::cin, line);
std::cout << line << '\n';
}
Then this will work:
var=$(./program)
I am trying to get the current running file name in C++. I wrote a simple code that uses both argv[0] and boost current_path() method. The file is compiled into executable file mainWindow.
#include "boost/filesystem.hpp"
int main(int argc, char* argv[])
{
boost::filesystem::path full_path( boost::filesystem::current_path() );
std::cout << full_path.string() << "\n";
std::cout << argv[0] << "\n\n";
return 0;
}
Interestingly the output of each method is different.
argv[0] output is:
../VENTOS/src/loggingWindow/mainWindow
current_path() output is:
/home/mani/Desktop/VENTOS_Redpine
I am not running my program (mainWindow) directly from the terminal. Another application is calling my program and I guess that's why the output is different. Am I right on this?
My second question is: Without using the argv[0] option and relying only on the boost filesystem methods, how can I get the same result as argv[0]?
argv[0] only contains the command used to execute the the program. This may contain the path. It may contain a relative path. It may contain no path at all. It might not even contain the executable name thanks to symlinks etc.... It might even be empty if the hosting system chooses to provide nothing. It can't be trusted, so you don't want to use this as a basis for evaluating other methods.
boost::filesystem::current_path fails you because it only returns the current working directory. This may or may not be the location of the executable because it depends on the directory from which the program was run and whether or not the working directory has been changed by the program. To be honest I'm not sure if there is a sure-fire way to get the process name and path from Boost. There wasn't a few years ago, but time has a way of marching on, you know?
There are a slew of questions covering how to get the executable and path (Finding current executable's path without /proc/self/exe looks promising but is stale. That time marching thing again.) but all are platform-specific you may have to do some ifdef or linker wizardry to make this work.
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 + "'))\"";
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);