开发者

C/C++ Is there any cross plataform way of using relative paths?

I'm programming a little game in SDL and the files are structured like this:

"src/game/" have both .h and .cpp source files.

"data/" have the game files like开发者_如何转开发 maps, tilesets, sprites and so on...

to load a sprite for example I would use the following code.

spriteLib.loadSprite("data/sprites/sprite-ghost.bmp");

to convert this string to an absolute path I have those lines in the first 4 lines of the function:

SSprite CSpriteLib::loadSprite(std::string file)
{
    //Converting the file path
    char converted[128];
    realpath(file.c_str(),converted);
    file = converted;

But this way the program only compiles under liux so... if anyone knows another way to do that I would be grateful.


Boost is your friend. Here's a link to the Boost Filesystem tutorial.


Few points:

char converted[128];
realpath(file.c_str(),converted);
  1. First of all realpath on some operating systems (Solaris) may still return the relative path.
  2. Your code contains buffer overflow, it is better to use canonicalize_file_name or char *m=realpath(file.c_str(),0); ... free(m); - however this is Linux specific. See man realpath to see how to use it more or less correctly.

Also how would realpath help you to open your data? If

fopen(converted,"r")

Works in your case then

fopen(file.c_str(),"r")

would work as well. It is provided to help removing all symbolic links, etc.

If you need some similar functionality to realpath, you may use GetFullPathName under Windows, but it still behaves differently.


Just wrote a tiny class for it:

#include <string>
#include <vector>
#include <iostream>

class CFilePath
{
        typedef std::vector<std::string> TPath;
    public:
        enum EPlatform
        {  
            Windows,
            Unix
        };
        CFilePath(EPlatform p_platform) : m_platform(p_platform) {}
        CFilePath& operator/(const char* p_path)
        {  
            m_path.push_back(p_path);
            return *this;
        }

        std::string GetPath()
        {  
            std::string ret;
            if (m_path.empty())
                return ret;
            for (unsigned i = 0; i < m_path.size();)
            {
                ret+=m_path[i];
                i++;
                if (i < m_path.size())
                {  
                    switch (m_platform)
                    {  
                        case Windows:
                            ret+="\\";
                            break;
                        case Unix:
                            ret+="/";
                            break;
                    }
                }
            }
            return ret;
        }
        operator const char*()
        {
            return GetPath().c_str();
        }
        EPlatform m_platform;

    private:
        std::vector<std::string> m_path;
};

int main(int argc, char* argv[])
{
    CFilePath::EPlatform platform = CFilePath::Windows; // variable
    CFilePath path(platform);
    path/"data"/"sprites"/"sprite-ghost.bmp";
    std::cout << path << std::endl;
    path.m_platform = CFilePath::Unix;
    std::cout << path << std::endl;

    return 0;
}

will prints:

data\sprites\sprite-ghost.bmp
data/sprites/sprite-ghost.bmp


My recommendation is: first, your main program should accept a native filename as an argument that represents where the data for the program live eg

C:\program files\mycompany\mygame

This passes the responsibility of deciding which data to use off to some other program (such as a bash script or driver or whatever).

Second, define the subparts of the directory space with the data in unix format so all filename literals in your program have this format. No ifs and buts, always Unix. Eg:

spriteLib.loadSprite("data/sprites/sprite-ghost.bmp");

Now write a function which combines the passed in directory name (in native format) with the unix filename translated to native format to get a suitable filename for access. You have already tried to do this but you're using an OS dependent function. Don't. Write it yourself. You want to get this out:

C:\program files\mycompany\mygame\data\sprites\sprite-ghost.bmp

The method of @Industrial-antidepressant (previously @nice blonde stupid girl) is quite good too, but it's a bit more work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜