Xcode loading program resources from my Home folder rather than Resources - C++ - c++

This is my first time using Xcode and it is appalling to me how completely non intuitive this IDE is. I heard it was better in the past and I really hope it was.
My problem is that the resources my program loads, a data file and an .ini file, it automatically searches for these file in my Home folder. I want for it to search for these files in the Resource folder of the .app. I am using C++ and all of the examples I have found are for Objective-C.
Any idea on how to fix this?

You are probably assuming that, when your app launches, the current working directory of the process is your app's bundle. It isn't. (Nothing to do with Xcode particularly -- that's just how OS X works.)
Typically you would use NSBundle (Objective-C) or CFBundle (C)
to find resources in your app bundle. Since you're using C++, let's use the C API.
To find the URL to a file "myFile.ini" in the Resources directory in your app bundle:
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef url = CFBundleCopyResourceURL(mainBundle, CFSTR("myFile"), CFSTR("ini"), NULL);
UInt8 filePath[PATH_MAX];
if (CFURLGetFileSystemRepresentation(url, true, filePath, sizeof(filePath)))
{
// use your API of choice to open and read the file at filePath
}
Or, to just change the CWD to your app bundle:
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef url = CFBundleCopyBundleURL(mainBundle);
UInt8 bundlePath[PATH_MAX];
if (CFURLGetFileSystemRepresentation(url, true, bundlePath, sizeof(bundlePath)))
{
if (chdir((const char*)bundlePath) == 0)
{
// now the CWD is your app bundle, and you can use relative path names to access files inside it
}
}

Related

How to read a file on Hololens with C++

I am trying to read a file in a test/debug UWP application that is being deployed to Hololens. I can put the file on the device with the device portal, but am unable to find the correct path to open the file.
I am using the MSFT BasicXrApp_uwp example as a basis, and have included FileUtility which has a FindFileInAppFolder function. This is consistently failing to find the file, with the error:
"The file should be embeded in app folder in debug build.",
after letting me know the app folder is:
C:\Data\Users\DefaultAccount\AppData\Local\DevelopmentFiles\364f83f4-6e13-42e4-8253-71dd3040951cVS.Debug_ARM.mikeh\
The part 364f83f4-6e13-42e4-8253-71dd3040951cVS is recognisable in the device portal as the User Folders/LocalAppData folder, but the Debug_ARM.mikeh part is not visible on the portal.
I am using C++ and trying to do the file reading in a static, non uwp library if possible (pointing that out so I don't get suggestions to use UWP async stuff, if that is possible).
So, how do I embed my file in the app folder, or how do I place the file so I can read it?
This is because the folder path which FindFileInAppFolder method returns is the InstalledLocation of the current package, but what you checked in the device portal is LocalFolder/LocalCacheFolder, for more information about what different between them please see: File access permissions.
how do I embed my file in the app folder, or how do I place the file so I can read it?
You can place your file in the LocalState folder by Device Portal and get this folder path through ApplicationData.LocalFolder Property, the path should be like: C:\Data\Users\DefaultAccount\AppData\Local\Packages\364f83f4-6e13-42e4-8253-71dd3040951c\LocalState. For how to access the files via C++ you can use for example File access sample
I'm using an answer here as there's more room than a comment.
I found a few extra things useful. I added in the cppWinRT nuget package to my application.
I did need to use the "async stuff", for example:
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
StorageFolder storageFolder= KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::PicturesLibrary).get();
This let me find a file I'd uploaded ot the Pictures Library. But I couldn't open it after passing the path to my existing library:
const auto sampleFile = storageFolder.GetFileAsync(fileName).get();
std::wstring path = sampleFile.Path();
MyLibraryCall(to_string(path));
MyLibraryCall would try and open an ifstream, and even using std::ifstream::in would fail.
So I copied the file to the temp directory, where I could open it and process it.
This is pretty hacky but it did what I needed, which is let me load an .obj file that was rejected by the 3D parts viewer.
The loop over all filenames is because storageFolder.GetFileAsync(fileName).get() throws an exception if it fails, which for me I could not catch properly.
StorageFolder tempFolder = Windows::Storage::ApplicationData::Current().TemporaryFolder();
std::wstring path;
auto files = tempFolder.GetFilesAsync().get();
for (auto file : files)
{
if (file.Name() == fileName) {
path = file.Path();
break;
}
}
if (!path.size()) {
// hasn't been copied into temp
StorageFile movedFile = sampleFile.CopyAsync(tempFolder).get();
path = movedFile.Path();
}
MyLibraryCall(to_string(path));
Anyway- not the greatest but that will hopefully help someone else looking for a quick and dirty way to process a file on a hololens/UWP app.

what is the proper method of using resource files in MFC project?

i have made a MFC-based game and my project includes images and sounds. Now i want to create an installer setup in order to distribute it.
i have used the resources by providing their exact path in e.g
img->Load(L"C:\\Users\\Ad33l's\\Desktop\\block mania\\block mania\\res\\db.png");
MCIWndCreate(NULL, NULL,WS_POPUP|MCIWNDF_NOPLAYBAR|MCIWNDF_NOMENU,L"C:\\Users\\Ad33l's\\Desktop\\block mania\\block mania\\res\\tick.wav");
1.Can someone tell me any way to avoid Hard-coding the actual resource path as these resource files will not be present at this same exact path in other computers ?
2.Also guide me to handle these resource files during the creation of standalone SETUP (i am using advance installer )
(as an actual answer).
Do not use absolute path, always use relative path; relative to your EXE file is one solution.
The EXE path can be found using GetModuleFileName.
char appPath[MAXFILENAMELEN];
GetModuleFileName(NULL, appPath, MAXFILENAMELEN);
(addendum) appPath name is misleading, it contains the full name of the application; you need to extract the path from the full application name.
We do something like this:
(edit to make it compilable in unicode)
TCHAR applicationPath[MAX_PATH];
GetModuleFileName(NULL, applicationPath, MAX_PATH);
CString sSoundFile(applicationPath);
PathRemoveFileSpec(sSoundFile.GetBuffer());
sSoundFile.ReleaseBuffer();
From there, you can do something like (pseudocode-ish):
img.Load( appPath + "//Images//db.png" );
You can have a variable that saves the directory they want to install your program in. After they choose the directory they want to install it in, go off of that. Or you can also use system folders like the appdata folder
A first solution would be to configure your setup project to install the installation files under the DesktopFolder\block mania\block mania\res. Then, you can access within your application the current user Desktop location and append to it the remaining fix location (block mania\block mania\res).
Another solution would be to configure the setup project to create registries at install time which will store the paths of the installation files. Then, your application could read the installation paths from registry.
Finally you could also create at install time environment variables containing the paths of the installation file and, then use within your application the environment variables to access the installed files locations.

Opening files on Android using Cocos2d-x api

I am having difficulty opening a file with cocos2d-x FileUtils in an android project. I am using Cocos2d-x v2.2.3 and the create_project.py to set up my project structure. There is a folder called Resources that contains some HelloWorld png's. I would like to add other files to this folder and then perform read operations with standard file stream operations. However, opening the file fails when running on the Android emulator. I have tried using CCFileUtils::sharedFileUtils()->getWritablePath() and then appending the name of the file. What is the correct way to use Cocos2d-x to open files on android?
The folder Resources contains files for which the app has only a read access.
To get the correct path to these files use:
string yourFilename = "hello.txt"; // only (relative path+) filename here, no absolute path!
string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(yourFilename.c_str());
Open the file using fullPath!
The routine searches in a number of paths which can be extended.
See description of CCFileUtils::fullPathForFilename()
To define the search paths and the search order write something like:
vector<string> searchPaths;
searchPaths.push_back("1st_path");
searchPaths.push_back("2nd_path");
searchPaths.push_back("3rd_path");
CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(searchPaths);
For Android apps the Resource folder is already part of the search paths, so no need to add it here.
To see the different paths try:
CCLOG ("full path: %s", fullPath.c_str());
CCLOG ("writable path: %s", CCFileUtils::sharedFileUtils()->getWritablePath().c_str());

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

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 );
}

How to reference Resources folder in code

I'm porting a c++ Qt application from Windows to OSX and cannot wrap my head around the .app bundle concept. I hope someone can help me understand.
My executable lives here: MyProgram.app/Content/MacOS/MyProgram.exe
My resource folder lives here: MyProgram.app/Content/Resources/
In my code I use a relative path to reference items in the resource folder:
"../Resources/something.png"
This works great if I open the .app bundle and run the .exe directly.
But that is not how the .app bundle is meant to work. The user is supposed to click on the .app bundle in the Finder to run the program. But in that case my relative path no longer works, and this is what I don't understand.
Does anyone understand my problem and how I can fix it?
QApplication::applicationDirPath()
http://doc.qt.io/qt-5/qcoreapplication.html#applicationDirPath
We use:
QDir
CoreDir::bundle()
{
// Trolltech provided example
CFURLRef appUrlRef = CFBundleCopyBundleURL( CFBundleGetMainBundle() );
CFStringRef macPath = CFURLCopyFileSystemPath( appUrlRef, kCFURLPOSIXPathStyle );
QString path = CFStringToQString( macPath );
CFRelease(appUrlRef);
CFRelease(macPath);
return QDir( path );
}
So do CoreDir::bundle().filePath( "../Resources" );
When you compile your product, have your tried setting the path of Resources to be relative? Otherwise, you can retrieve the main bundle, the URL of the app thereof and append it to the Resources URL.
Bundle Programming Guide
There's a manual for everything, it seems :)