网上有很多帖子详细说明了相对路径在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包中工作的相对路径?
答案 0 :(得分:63)
让我花了大约5个小时的谷歌并尝试不同的事情来最终找到答案!
#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(我开发跨平台)并使代码更好。
我感谢其他两个人的答案,你的帮助最终让我找到了正确的答案,所以我已经投票给你了。谢谢你们!!!!
答案 1 :(得分:12)
不要依赖二进制代码中的当前工作目录。只是不要。在Mac,Windows或Unix上,您无法信任操作系统或shell将其设置为您希望设置的位置。
对于直接C,在dyld.h中使用_NSGetExecutablePath来获取当前可执行文件的路径,然后你可以从那里开始相对。
如果您只是尝试并希望它能够正常工作,请在Xcode中选择Project&gt;编辑Active Executable,其中有一个面板,您可以在其中将初始工作目录设置为项目目录,可执行文件的父目录或任意目录。这应仅用于测试目的。在Mac OS中,当您编写一个真实的应用程序并从Finder启动它时,工作目录是/。对于Unix应用程序,您无法控制工作目录。
答案 2 :(得分:2)
我的猜测是你正在构建的应用程序类型是一次性可执行文件而不是可执行应用程序包。在OS X和Unix上,一般来说,资源是从驱动器的绝对根加载的,这与Visual C ++对“root”的处理不同,后者是相对于项目根的路径。不要依赖于特定于操作系统(或OS操作系统版本)之间的任何相关路径。您可以在Xcode中设置工作目录,但这只会影响从Xcode启动的应用程序。如果您要从Finder中的构建目录执行它,它将再次被设置为驱动器的根目录。
答案 3 :(得分:0)
只是关于相对路径和xcode的评论。
我最近注意到,如果您的应用没有可以复制到资源文件夹中的文件,则当前工作目录将设置为实际.app的目录 - 例如,在以下级别:myApp.app
但是,如果您将一个文件添加到项目中并将其复制到应用程序包的Resources文件夹中,则会将.cwd设置为.app内的3级深度。例如,在myApp.app/Contents/MacOS/myApp
的级别似乎xcode正在尝试为您提供智能,并假设您的应用程序包中没有资源,那么您希望将文件加载到.app级别而不是内部可执行文件级别。
即使从Finder启动应用程序,这仍然存在。所以也许是避免相对路径的另一个原因。
答案 4 :(得分:-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->LoadMusic(GetLoadFilename("Audio/Pop.wav"));
。