Mac osx c++ .app cannot find a file fopen() - c++

I have a folder in the same directory as my mac .app and in it is a file called test.ssm. This is trying to be opened by this function:
FILE *input_file = fopen("./data/maps/test.ssm", "r");
The problem is that the application keeps getting the code: EXC_BAD_ACCESS, because it cannot open this file. My project has been set up in xcode using a normal coccoa project. This is an opengl/glut application.

The problem is that a .app is a package, and therefore it is actually a directory structure as well, not a "normal" file. Your actual executable is inside the directory YourApp.app/Contents/MacOSX/. Thus when you use a relative path starting with ./ to open a file in C-code, the executable is actually looking for your file inside the YourApp.app/Contents/MacOSX/ directory, and not the parent directory that the .app package is installed in.
You can actually browse the directory structure of your .app by right-clicking on it and choosing View Package Contents.
If you are going to place files in the file-system that you would like accessible from your executable, either package them inside the .app, or place them outside the .app, and place enough ../ in your file access to get you out of the .app directory structure and into the parent directory where the .app is installed.
If you want your /data directory to be inside the .app package, then you would only have to add enough ../ to your path to get you to out of your /MacOSX directory and into the root of the .app where the /data directory would be found.
Finally, if you need to know the absolute path where your executable is located, you can always use the C-function _NSGetExecutablePath found inside of mach-o/dyld.h (i.e., you don't need objective-C). From there you can modify the path to get at any other directory in the file-system relative to where your executable is by trimming it to the proper parent directory and then appending the path name to the file you want to open.

You have to provide absolute file path in Mac OS X, because Mac OS X is built to work with file dialogs or something like that.

As said above, the .app is a package, or a special folder that the Mac OS X GUI treats like a file. The .app isn't what's being run, what's being run is your.app/Contents/MacOS/your, and the current directory refers to your.app/Contents/MacOS/. If you don't mind using Objective-C in your app (if you're not linking Foundation.framework already I'd advise you find another way), you can do this to get the path of the app bundle:
const std::string GetApplicationDirectory()
{
id info = [[NSBundle mainBundle] infoDictionary];
NSString *bundleID = [info objectForKey: #"CFBundleIdentifier"];
NSWorkspace *wp = [[NSWorkspace alloc] init];
NSString *app = [wp absolutePathForAppBundleWithIdentifier: bundleID];
const char *str = [[app substringToIndex: [app length] - [[app lastPathComponent] length]]] cStringUsingEncoding: NSASCIIStringEncoding];
return std::string( str );
}

Related

why std::filesystem::current_path() returns different variables when im in editor and using .exe

I have my project where i am using filesystem to retrieve directory of assets.
When i am lunching my program in editor(im using Visual Studio 2019) everything is fine and this code return value of working direcotry of project.
std::string currentPath = std::filesystem::current_path().string();
But when i am lunching app from .exe file this line of code returns path that leads to .exe file.
The same directory called $TargetPath in properties in VS.
So my question is why is that happening and how can i resolve this problem.Becouse of that i cannot automatically load assets when lounching app from .exe file
Because it gives the current working directory, which is set by the environment calling your program (unless your program explicitly changes it).
So, it does what it's designed to do, gives the current working directory:
Returns the absolute path of the current working directory,
So my question is why is that happening
It happens because you've configured the editor to set the working directory to one path, while you're running the program with another working directory outside the editor.
how can i resolve this problem.Becouse of that i cannot automatically load assets when lounching app from .exe file
Here is an approach:
Store the assets in a path that is relative to the exe.
Get path to the exe.
On POSIX, you can use argv[0] from arguments of main
On Windows, the documentation recommends GetModuleFileNameW
Get canonical absolute form of that path (make sure that working directory hasn't been changed before this step if the path to exe is relative).
Get the directory that contains the exe from that canonical path.
Join that directory path with the asset's relative path to get an absolute path to the asset
Load the asset using the absolute path.

File not being created in correct directory C++

I'm trying to use fstream to create a file, however the file i'm trying to create wont appear in the .exe directory or anywhere else in the file directory. After searching in my computer for the file, I found that was created in a different directory entirely even though i'm using a relative directory.
This is the code to create the file:
ofstream file;
file.open("something.jpg", ios::out|ios::binary|ios::beg);
Directory of created file: C:\Users\user-pc
Directory of project: D:\Users\user-pc\Documents\Visual Studio 2012\Projects\recvFile
by the way, using an absolute directory works perfectly fine. Could this be a problem with the projects working directory?
In your Visual Studio right-click on your project, click Properties, then go to Configuration Properties, then Debugging. There is a row "Working Directory". You can set the working directory there. If you need to do this programmatically, you can use SetCurrentDirectory .
If you need to create the file in the same directory as the .exe location, you can use this approach: https://stackoverflow.com/a/124901/1915854
Call GetModuleFileName() using 0 as a module handle...
If the .exe is installed in a shared directory like Program Files, then creation of the file in the same directory could require additional permissions and may be a bad idea. If the .exe is just cloned to the directory where it should create files, then there is no such problem.
Try adding "../" to the link:
file.open("../something.jpg", ios::out|ios::binary|ios::beg);
File will be created in Debug/Release folder of your project. try what Timo Rzipa suggested.

Qt: Telling a program to read other files from the same directory as it's placed in

I have a program which is going to take a few different files as input.
All I am going to know is that the files are going to be in the same folder as my program (and I know their names).
Is there a way to write a path to a file knowing only its name and that it will be in the same folder as the main program?
If you are sure the files are in the same folder of your program you could use:
QCoreApplication::applicationFilePath()
You are looking for these from QCoreApplication.
QString QCoreApplication::applicationDirPath() [static]
Returns the directory that contains the application executable.
For example, if you have installed Qt in the C:\Qt directory, and you run the regexp example, this function will return "C:/Qt/examples/tools/regexp".
On Mac OS X this will point to the directory actually containing the executable, which may be inside of an application bundle (if the application is bundled)
Warning: On Linux, this function will try to get the path from the /proc file system. If that fails, it assumes that argv[0] contains the absolute file name of the executable. The function also assumes that the current directory has not been changed by the application.
and
QString QCoreApplication::applicationFilePath() [static]
Returns the file path of the application executable.
For example, if you have installed Qt in the /usr/local/qt directory, and you run the regexp example, this function will return "/usr/local/qt/examples/tools/regexp/regexp".
Warning: On Linux, this function will try to get the path from the /proc file system. If that fails, it assumes that argv[0] contains the absolute file name of the executable. The function also assumes that the current directory has not been changed by the application.
Depending on your exact use case, you use one of them, probably the former if you wish to get the executable path + your other files appended.

Open txt file with default program

In my program, I have a button that I want to open a text file in a relative directory. I'm using QDesktopServices like this:
QDesktopServices::openUrl(QUrl::fromLocalFile("file:///stuff/block_settings.txt"));
When the button is pressed, nothing happens.
The file is in a folder named "stuff" that resides in the same location as my .exe. It is the same directory used for all my other tasks.
What am I doing wrong?
Thanks.
The file is in a folder named "stuff" that resides in the same location as my .exe. It is the same directory used for all my other tasks. What am I doing wrong?
Seems like your full path is an overcomplication. I would suggest to use this intead:
QString QCoreApplication::applicationDirPath() [static]
Returns the directory that contains the application executable.
For example, if you have installed Qt in the C:\Qt directory, and you run the regexp example, this function will return "C:/Qt/examples/tools/regexp".
On Mac OS X this will point to the directory actually containing the executable, which may be inside of an application bundle (if the application is bundled).
Warning: On Linux, this function will try to get the path from the /proc file system. If that fails, it assumes that argv[0] contains the absolute file name of the executable. The function also assumes that the current directory has not been changed by the application.
So, you would be writing this code:
QDesktopServices::openUrl(QString("%1/stuff/block_settings.txt")
.arg(QCoreApplication::applicationDirPath()));
I fixed the issue. Changed to:
QDesktopServices::openUrl(QUrl("file:stuff\\block_settings.txt"));
Not sure how that works because I don't see that configuration on any tutorial anywhere but w/e

Relative path problem for a deployed win32 application

I have written a c++ program and deployed it in say c:\my_app, and my executable's path is c:\my_app\my_app.exe. Say, my_app needs many files such as the_file.txt, which is located in c:\my_app\the_file.txt.
In my executable, I open the txt file as, xx.open("the_file.txt");
Moreover, I have associated my program with let's say .myp extension.
When I'm on Desktop, and want to open a file named example.myp, my program can not see the_file.txt. Because, it (somehow) assumes that it's currently working on Desktop.
Is there any easy way to handle this problem by changing shell command for open in HKEY_CLASSES_ROOT? The naive solution would be to change all file open operations with something like %my_app_location/the_file.txt". I don't want to do that.
Always use a full path name to open a file. In other words, don't open "foo.txt", open "c:\bar\foo.txt". To find the install directory of your EXE use GetModuleFileName(), passing NULL for the module handle.
These days you shouldn't add files to c:\my_app....
Instead use the ProgramData Folder and full paths.
Use SHGetSpecialFolderPathA with CSIDL_COMMON_APPDATA to get the ProgramData folder and the create your program directory and add your files.
You should set current directory for your app's folder with SetCurrentDirectory function. After that you can open file by name without full path