C++ File Paths Issue - c++

When I use this code to load an image for SDL to render:
SDL_Texture* testimg = IMG_LoadTexture(renderer, "testz.bmp");
(or)
SDL_Texture* testimg = IMG_LoadTexture(renderer, "/testz.bmp");
the image doesn't render at all. However... if I use this code:
SDL_Texture* testimg = IMG_LoadTexture(renderer, "../bin/testz.bmp");
SDL draws the image just fine. "bin" is the folder the .exe is in. So how do I fix this file paths issue?
edit: another possibility may be that visual studio, for some reason, is running the exe it put in the bin folder in another location which doesnt have the image...

Because the directory where your executable is installed is not the same thing as the current directory of the process that your operating system starts, when it runs this executable.
It's fairly obvious that the current directory of your started process is the sibling directory of its executable.

One thing that might work is to use argv[0] to make sure the correct base path is used. Assuming you're using standard main(), it would go something like this:
std::string base_path;
int main(int argc, char* argv[]) {
base_path = argv[0];
size_t last_slash = base_path.find_last_of('/');
if(last_slash == std::string::npos)
base_path = ".";
else base_path.erase(last_slash + 1);
// Anything else you need to do in `main()`
return 0;
}
And then your loading would look like this:
SDL_Texture* testimg = IMG_LoadTexture(renderer, base_path + "testz.bmp");
If it's in a different file than main(), you'll also need to redeclare base_path with extern:
extern std::string base_path;
And of course you need to #include <string> for this to work.
If all your loading is done in main(), you can make this a bit better by moving the declaration of base_path into main():
int main(int argc, char* argv[]) {
std::string base_path = argv[0];
// The rest is the same
}

Related

c++ simpleini example on getting a ini file from a directory?

hi could someone help me i'm trying getting the liberty simpleini for c++ to read/write a file from a different directory but so far nothing is working.
using windows 7
#include "SimpleIni.h"
#include <stdio.h>
int main( int argc, char** argv)
{
CSimpleIniA ini;
ini.SetValue("test", "default", "1");
ini.SaveFile("c:\\test\\test.ini");
//tried ini.SaveFile("c:\test\test.ini");
ini.LoadFile("c:\\test\\test.ini");
//tried ini.LoadFile("c:\test\test.ini");
const char * set = ini.GetValue("test", "default", "");
printf( "value = %s", set ); // should load from c:\test\test.ini
return 0;
}
source http://code.jellycan.com/simpleini-doc/html/index.html
The problem is in that it doesn't create directories.
You should create "c:\test" directory first on your own and then start application.
I started with your code and it didn't work, then I created "test" folder on drive C and it began to.

stat() doesn't find a file in c++

on Linux 12.04
I have an executable file located in say:
/a/b/exe
and a config file on
/a/b/config
when doing:
cd /a/b/
./exe
everything's ok and the stat function finds the file config on /a/b/
HOWEVER,when running from root
/a/b/exe
the stat doesn't find the config file
any idea why?
it makes it impossible to run the binary using a script that isn't ran from the folder of the exe.
Edit
The call looks like this:
struct stat stFileInfo;
bool blnReturn;
int intStat;
// Attempt to get the file attributes
intStat = stat(strFilename.c_str(),&stFileInfo);
if(intStat == 0) {
// We were able to get the file attributes
// so the file obviously exists.
blnReturn = true;
} else {
// We were not able to get the file attributes.
// This may mean that we don't have permission to
// access the folder which contains this file. If you
// need to do that level of checking, lookup the
// return values of stat which will give you
// more details on why stat failed.
blnReturn = false;
}
In first case cd ..., run exe you change current working directory before executing the program, in second case you launch exe without changing current working directory, and I think in your program you use a relative path to open your config(for example ./config or just config) and it can't find it from current working directory. easiest workaround is to change working directory at start of your app:
int main(int argc, char** argv) {
std::string s( argv[0] ); // path to the program
std::string::size_type n = s.rfind( '/' );
if( n != std::string::npos ) {
std::system( ("cd " + s.substr(0, n)).c_str() );
}
// rest of your code
}

C++ Find execution path on Mac

Lets say my executable is located at /Users/test_user/app on Mac OSX and I am running it from /Users/test_user/Desktop/run_app:
Desktop run_app$ /Users/test_user/app/exec
Within my C++ code how can I find the path to the location of the executable (which in this case would be /users/test_user/app)? I need to reference some other files at this path within my code and do not want to put absolute paths within the code as some users might place the folder in a different location.
man 3 dyld says:
_NSGetExecutablePath() copies the path of the main executable into the
buffer buf. The bufsize parameter should initially be the size of the
buffer. This function returns 0 if the path was successfully copied.
It returns -1 if the buffer is not large enough, and * bufsize is set
to the size required. Note that _NSGetExecutablePath() will return "a
path" to the executable not a "real path" to the executable. That is,
the path may be a symbolic link and not the real file. With deep
directories the total bufsize needed could be more than MAXPATHLEN.
#include <mach-o/dyld.h>
#include <limits.h>
int main(int argc, char **argv)
{
char buf [PATH_MAX];
uint32_t bufsize = PATH_MAX;
if(!_NSGetExecutablePath(buf, &bufsize))
puts(buf);
return 0;
}
Provided I'm understanding you correctly, you should be able to use NSProcessInfo's -arguments method to get the executable path.
To mix in Objective-C code with C++ code, you can just change the filename extension of the source file in question from .cpp to .mm. Then add the Foundation.framework to the Link Binary With Library build phase of your Target.
[EDIT] updated to show the difference between argv[0] and [[[NSProcessInfo processInfo] arguments] objectAtIndex:0].
Then to use the code, you could do something like in the following code:
#include <iostream>
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// print out raw args
NSMutableArray *arguments = [NSMutableArray array];
for (NSUInteger i = 0; i < argc; i++) {
NSString *argument = [NSString stringWithUTF8String:argv[i]];
if (argument) [arguments addObject:argument];
}
NSLog(#"arguments == %#", arguments);
const char *executablePath =
[[[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
fileSystemRepresentation];
printf("executablePath == %s\n", executablePath);
const char *executableDir =
[[[[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
stringByDeletingLastPathComponent] fileSystemRepresentation];
printf("executableDir == %s\n", executableDir);
[pool release];
return 0;
}
If I then cd into the parent directory of the executable, and then execute the executable using a relative path:
MacPro:~ mdouma46$ cd /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug
MacPro:Debug mdouma46$ ./executablePath blah blah2
I get the following output:
2011-08-10 12:59:52.161 executablePath[43554:707] arguments == (
"./executablePath",
blah,
blah2
)
executablePath == /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug/executablePath
executableDir == /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug
So, while argv[0] may not necessarily be a full path, the result returned from [[[NSProcessInfo processInfo] arguments] objectAtIndex:0] will be.
So, there's [[[NSProcessInfo processInfo] arguments] objectAtIndex:0], or a slightly simpler approach is just to use NSBundle itself, even if it is a command-line tool (see What is the "main bundle" of a command-line foundation tool?):
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
const char *executablePath =
[[[NSBundle mainBundle] executablePath] fileSystemRepresentation];
[pool release];
Maybe you could use the which command. http://unixhelp.ed.ac.uk/CGI/man-cgi?which
If it's a "real" OS X application the proper way to do it is to create a bundle:
http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFBundleRef/Reference/reference.html

Program cannot open file, but the file is already there

I am writing a program that will open an image file, but strange thing happened. This is the output from cmd:
C:\Users\Karl\Pictures>testcvconsole mypic.jpg
argv[0]==testcvconsole
argv[1]==mypic.jpg
fopen is null
strerror(errno)==No such file or directory
Are there something I should consider when fopen simply failed to open my file when the file is right there along side with the executable file in the same directory?
This is on Windows 7, Visual Studios Express 2010. C++.
EDIT: code below
#include "stdafx.h"
#include <string.h>
#include <errno.h>
int goMain(int argc, char** argv);
int _tmain(int argc, _TCHAR* argv[])
{
goMain(argc, (char**)argv);
return 0;
}
int goMain( int argc, char** argv ){
if (argv[1] != NULL){
printf("argv[0]==%S\nargv[1]==%S\n", argv[0], argv[1]);
if (fopen(argv[1], "r") == NULL){
printf("fopen is null\n");
printf(strerror(errno));
}
}
return 0;
}
EDIT2:
I have tried
char *workingDir =_getcwd(NULL, 0);
printf("workingDir == %S", workingDir);
as TomK has suggested and it returned:
workingDir ==
Nothing at all. Hmm...
EDIT3:
I am getting something. I tried
argv[1] = "C:/Users/Karl/Pictures/mypic.jpg";
And fopen can open it. This statement above is inserted right before the fopen.
Make absolutely sure they are in the same directory. I'm saying this because you're using Visual Studio, for which the "same" directory isn't always so clear, because it depends on how you execute the executable through the IDE.
C:\Users\Karl\Pictures>testcvconsole mypic.jpg
Are you sure mypic.jpg is located in C:\Users\Karl\Pictures ?
Can u check whether the working directory is correct?
#include <direct.h>
char *workingDir =_getcwd(NULL, 0);
Can you run your application with admin privileges?
Usually the .exe is created in sub-directory either Debug or Release - try giving the absolute path to the image ...
I've had this problem, and it turned out that Visual Studio's runtime wasn't setting the current directory. I never figured out the problem: instead I simply used an absolute path. Without the absolute path, your program is looking in C:\. You can also try using ".\\mypic.jpg" or GetCurrentDirectory().

Newbie problem with QT C++ - Qimage dont work?

I am trying to do console application to read pixels from image:
#include <QtCore/QCoreApplication>
#include <QtGui/QImage>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QImage *img = new QImage("adadad.jpg");
//std::cout << "Type filename:" << std::endl;
img->isNull();
return a.exec();
}
That doesn't work I got: (IT doesn't compile, but anyway file isn't exist yet...)
File not found: tmp/obj/debug_shared/main.o:: In function `main':
What is going on? Is it impossible to use Qimage with console app?!
EDIT:
screen
It is possible to use QImage in a console application, you must make sure that QtGui is configured though. If you chose a console app, your .pro file might contain something like
CONFIG += console
QT -= gui
If that's the case, remove the QT -= gui line.
QImage("adadad.jpg");
Will probably look for a file called adadad.jpg on the current working directory for your application. Check if that file is present. Otherwise, use a fully qualified path.
img->isNull() doesn't do anything on it's own, try this instead:
if(img->isNull())
std::cout << "Image isNull!\n";
else
std::cout << "Image loaded\n";
My guess is that the local directory of the executable is not the same as the location of that image, so Qt can't find the file. Try specifying the complete path.
EDIT: Ahh... didn't realize it was a compilation problem. That looks suspiciously like a moc issue. What build system are you using? and can you confirm that the moc step is executing?
This modification of your code will compile and run as expected if there is a valid image file in the current working directory when you run the app. It will display Image loaded
#include <QtGui/QImage>
#include <iostream>
int main(int argc, char *argv[])
{
QImage *img = new QImage("adadad.jpg");
if(img->isNull())
std::cout << "Image is null";
else
std::cout << "Image loaded";
return 0;
}
You do not need to create an instance of QCoreApplication unless you have subclassed it and put your program code in that subclass.
Update:
Your program does not exit so you are probably getting that compile error because it can't replace the executable because it is still running (and locked). The file locking is more likely to be an issue under Windows.
An important note when you are loading a file using directly "adadad.jpg" in your code. Even if you put the file inside the debug/release folder, QImage will always be null if loaded this way.
I run into this problem yesterday and I fixed it by using the Qt library to get the full path: QCoreApplication::applicationDirPath().
There is two way to achieve that, first one is when you create the img object.
QImage img( QCoreApplication::applicationDirPath() + "adadad.jpg");
if( img.isNull())
{
qDebug() << "Loading Error - file: adadad.jpg.";
return false;
}
or using the load function
QImage img;
if( !img.load(QCoreApplication::applicationDirPath() + "adadad.jpg"))
{
qDebug() << "Loading Error - file: adadad.jpg.";
return false;
}