33

网上有很多帖子详细说明了相对路径如何在 Xcode 中不起作用。我确实有一个 Xcode 模板,我下载了相对路径可以工作的地方,但是我无法弄清楚为什么也无法在其他项目中复制它。

首先,我在 Xcode 3.1 中使用 C++。我没有使用 Objective-C,也没有使用任何 Cocoa/Carbon 框架,只是纯 C++。

这是在我的其他 Xcode 模板中工作的代码:

sound->LoadMusic( (std::string) "Resources/Audio/Pop.wav" );

这个相对路径在 Windows 中也适用于我。运行以下命令为我提供了应用程序完整路径的绝对路径:

std::cout << "Current directory is: " << getcwd( buffer, 1000) << "\n";

/应用程序/myApp

我们如何获得在 Xcode .app 包中工作的相对路径?

4

5 回答 5

65

我花了大约 5 个小时的 Google 并尝试了不同的方法,终于找到了答案!

#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#endif

// ----------------------------------------------------------------------------
// This makes relative paths work in C++ in Xcode by changing directory to the Resources folder inside the .app bundle
#ifdef __APPLE__    
    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
    char path[PATH_MAX];
    if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
    {
        // error!
    }
    CFRelease(resourcesURL);

    chdir(path);
    std::cout << "Current Path: " << path << std::endl;
#endif
// ----------------------------------------------------------------------------

我抛出了一些额外的包含守卫,因为这使得它只编译 Apple(我开发跨平台)并使代码更好。

我感谢其他 2 个人的回答,您的帮助最终使我走上了正确的轨道,找到了这个答案,所以我投了你们俩的票。多谢你们!!!!

于 2009-02-06T16:19:06.653 回答
12

不要依赖二进制代码中的当前工作目录。只是不要。在 Mac、Windows 或 Unix 上,您不能相信操作系统或 shell 会将其设置为您期望的位置。

对于直接 C,使用 dyld.h 中的 _NSGetExecutablePath 来获取当前可执行文件的路径,然后你可以从那里去相对。

如果您只是在试验并希望它工作,请在 Xcode 中选择 Project > Edit Active Executable,那里有一个面板,您可以在其中将初始工作目录设置为项目目录、可执行文件的父目录或任何任意目录。这应该只用于测试目的。在 Mac OS 中,当您编写一个真正的应用程序并从 Finder 启动它时,工作目录是 /。对于 Unix 应用程序,您无法控制工作目录是什么。

于 2009-02-06T05:01:31.717 回答
2

我的猜测是您正在构建的应用程序类型是一次性可执行文件,而不是可执行的应用程序包。一般来说,在 OS X 和 Unix 上,资源是从驱动器的绝对根目录加载的,这与 Visual C++ 将“根”作为相对于项目根目录的路径的处理方式不同。不要依赖与任何特别是跨操作系统(或就此而言的操作系统版本)的任何东西相关的路径。您可以在 Xcode 中设置工作目录,但这只会影响从 Xcode 启动的应用程序。如果您要从 Finder 的构建目录中执行它,它会再次设置为驱动器的根目录。

于 2009-02-06T05:07:29.300 回答
0

只是关于相对路径和 xcode 的评论。

我最近注意到,如果您的应用程序没有将被复制到资源文件夹中的文件,则当前工作目录设置为实际 .app 的目录 - 例如在以下级别:myApp.app

但是,如果您将文件添加到项目中并将其复制到应用程序包的 Resources 文件夹中,它会将 cwd 设置为 .app 内部的 3 层。例如在 myApp.app/Contents/MacOS/myApp 级别

似乎 xcode 正试图为您提供智能,并假设您的应用程序包中没有资源,那么您将希望加载 .app 级别的文件,而不是内部可执行文件级别。

即使从 Finder 启动应用程序,这种情况仍然存在。所以也许是避免相对路径的另一个原因。

于 2010-01-14T11:56:37.957 回答
-1

如果您像我一样使用 SDL,则SDL_GetBasePath()返回 OSX 上的资源目录。

这是一个简单的包装函数:

std::string GetLoadFilename( const std::string& filename ) {
    std::string path;
    auto* base_path = SDL_GetBasePath();
    if( base_path == nullptr )
        return "./"+filename;
    path = std::string(base_path);
    path += filename;
    SDL_free(base_path);
    return path;
}

可以像sound->LoadMusic(GetLoadFilename("Audio/Pop.wav"));使用 OP 的问题一样调用它。

于 2021-04-06T13:48:53.033 回答