Search code examples
sdlsdl-2

Can SDL_GetBasePath() and SDL_GetPrefPath() be called before SDL_Init()?


In my application I would like to use a configuration file. However I have the chicken and egg problem here: the configuration file can even describe how SDL (and other things) should be init'ed. Thus, I would need to call SDL_GetPrefPath() before even SDL_Init() to get the common place where configuration for my application is stored as per-user basis. I'm not sure if it's possible. I also need SDL_GetBasePath() for similar (fall-back) purpose, I know that's ugly but some users would like that optionally for trying to find the configuration file. Reading the configuration file itself is not a problem, as I don't use SDL related functions for that, though I need to get the directory where configuration file can be found.

Surely, I can test if it's work, but it's not the best, it may fail in different SDL versions, on other architecture, or who knows. I would like to know it's safe "by design" (and "future-proof"), or not.

On the SDL-2 wiki, some functions like SDL_ShowSimpleMessageBox() is noted, that it's safe to be used even before SDL_Init(), but I am not sure if this is the situation in this case. I'm not sure if SDL-2 wiki is detailed enough to always show the situation like this (as with SDL_ShowSimpleMessageBox()), since this information is not mentioned on the pages of the functions I'm talking about now.

Note, my application is intended to run on Linux, MacOS and Windows, so it would be hard to judge by myself where SDL will put its preference directory after initialization, and also an ugly, redundant stuff then ...


Solution

  • Maybe it's useful for others too, so this is what I could figure out:

    https://bugzilla.libsdl.org/show_bug.cgi?id=3796

    I've submitted an SDL bugzilla ticket about this. The answer, that it's basically platform dependent, and not safe for these functions to be used without SDL_Init(). May work on some platforms, may not on others (or in the future). However, I got a tip, to use SDL_Init(0) and SDL_Quit() around the call. So, with my own ideas added as well, something like this:

    char *my_pref_dir_path = NULL;
    if (!SDL_Init(0)) {
        char *p = SDL_GetPrefPath(app_org, app_name);
        if (p) {
            my_pref_dir_path = strdup(p);
            SDL_free(p);
        }
        SQL_Quit();
    }
    if (!my_pref_dir_path) {
        /* ... panic or exit or whatever ... */
    }
    

    SDL_Init(0) won't initialize too much (not even video or other subsystems, so it won't interfere with the plan that I may not need SDL at all later), but it should be safe now to use the desired functions. After that, SQL_Quit() would make SDL "go away". Later, of course, you can have a "proper" SDL initialization, for example: SDL_Init(SDL_INIT_EVERYTHING), just like if this code hasn't been in your program at all before.

    Since, I am not sure, if the pointer returned by SDL_GetPrefPath() is valid after SQL_Quit(), I would strdup() it or such, and I use SDL_free() before SQL_Quit() on the pointer returned by SDL_GetPrefPath() since it's recommended by the documentation too anyway. Maybe I'm just too careful here, but I think, it's a safer bet then, if I play tricks like this.

    After this code, my_pref_dir_path will hold a pointer to the SDL preferences directory string, or NULL, if an error occured.