0

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...

Accumulator
  • 873
  • 1
  • 13
  • 34
  • Did you try `"./testz.bmp"`? – honk Jul 12 '15 at 19:54
  • Just tried it, it doesn't work. – Accumulator Jul 12 '15 at 19:54
  • Run your exe with the `bin` folder as working directory. – πάντα ῥεῖ Jul 12 '15 at 19:54
  • Try looking at the "current working directory" of your application. Development environments may place this slightly differently than a terminal would. You can find the current working firectory with `getcwd()`. You can explicitly change in in your code or you can check the development environments configuration (there will be an option to change it). – Martin York Jul 13 '15 at 02:14

2 Answers2

0

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.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

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
}
celticminstrel
  • 1,637
  • 13
  • 21
  • This is unreliable, because there are almost no guarantees about `argv[0]`. There is no guarantee that it has a path, and there's no guarantee that it's encoded in a way that can represent an arbitrary path (with Windows' convention of ANSI character encoding that would be a short name path, and AFAIK no compiler does that). For Windows one can use `GetModuleFileName(0)` to get the executable's path. – Cheers and hth. - Alf Jul 12 '15 at 20:16
  • Perhaps. However, a technique similar to this (but using `boost::filesystem::path` instead of `std::string`) has worked just fine for me both on Mac (which I think should have guarantees about argv[0] due to POSIX? Not certain though) and on Windows. – celticminstrel Jul 12 '15 at 20:21
  • POSIX gives no such guarantee, sorry. And neither does Windows. See http://stackoverflow.com/a/2051047/464581 for some practical code. It's not perfect but it's in the right direction. Like very concrete hinting. ;-) – Cheers and hth. - Alf Jul 12 '15 at 21:17
  • Even so, using `argv[0]` will work in most environments. Of course, the original poster could use that `GetModuleFileName(0)` in place of `argv[0]` if they're worried, like you suggested. And once you have the executable path, the rest of what I describe in this post would be the same. – celticminstrel Jul 12 '15 at 22:06