相对路径在 Xcode C++ 中不起作用

Posted

技术标签:

【中文标题】相对路径在 Xcode C++ 中不起作用【英文标题】:Relative Paths Not Working in Xcode C++ 【发布时间】:2010-10-05 16:43:48 【问题描述】:

网上有很多帖子详细说明了相对路径如何在 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";

/Applications/myApp

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

【问题讨论】:

感谢您的支持 - 我一直在苦苦挣扎好几个小时,试图让它在我自己的跨平台代码中工作。 当然没问题。我花了很多时间来解决这个问题。很高兴它可以帮助别人。哦,如果你愿意,你可以投票给我的问题/答案:D 【参考方案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;

如果使用OP的问题,可以称为sound-&gt;LoadMusic(GetLoadFilename("Audio/Pop.wav"));

【讨论】:

【参考方案2】:

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

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

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

【讨论】:

感谢您的 cmets cdespinosa,我正在尝试访问 myApp.app 包中的资源。您所说的关于编辑活动可执行文件的内容有效,但是一旦移动 myApp.app,它就不再有效,因为这不是相对路径,而是绝对路径 最终我试图访问 .app 包内的资源。这是可能的,我有另一个 Xcode 项目模板,其中相对路径可以工作,但是模板中没有代码。它默认工作。从这个模板编译的 .app 可以移动到其他地方,路径仍然有效 我之前忘了提这个。我正在做 chdir((const char*)argv[0]),但无论我做什么,它都不会改变当前目录。嗯 最好使用 Core Foundation,而不是使用私有 API(带下划线)。【参考方案3】:

我用了大约 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 个人的回答,您的帮助最终让我走上了正确的轨道,找到了这个答案,所以我投票给你们两个。谢谢大家!!!!

【讨论】:

你不知道这有多大帮助。感谢发布! 不错!这让我省了很多麻烦! 架构 i386 的未定义符号:“_CFBundleCopyResourcesDirectoryURL”,引用自:player-1308A7B7A421D47D 中的 player::player()。o “_CFBundleGetMainBundle”,引用自:player-1308A7B7A421D47D 中的 player::player() .o “_CFRelease”,引用自:player-1308A7B7A421D47D 中的 player::player() i386 添加 CoreFoundation 框架以解决与 undefined _CF* 相关的链接错误【参考方案4】:

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

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

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

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

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

【讨论】:

【参考方案5】:

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

【讨论】:

不,他正在尝试使用 OSX 的标准 .app 系统,在 .app 下有 /Contents,然后在 /MacOS 和 /Resources 下。在任何情况下,它都绝对不是相对于驱动器的绝对根。 Mac 可能是 unix,但该系统更类似于 chroot jail(某种),而不是您将在 linux 和传统 unix 中看到的标准 /usr/bin/executable 类型的应用程序。跨度>

以上是关于相对路径在 Xcode C++ 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

打字稿路径在 Express 项目中不起作用

为啥图像文字在 Xcode 11.2.1 中不起作用?

“添加断点”快捷方式在 xcode 4.3 中不起作用

“图像文字”命令在 Xcode 中不起作用

注册远程通知在 Xcode 6 中不起作用

NSKeyedArchiver 在 Swift 3 (Xcode 8) 中不起作用