相对路径在 Xcode C++ 中不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/516200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Relative Paths Not Working in Xcode C++
提问by Brock Woolf
There are numerous post over the net that detail how relative paths don't work in Xcode. I do have an Xcode template that I downloaded where the relative paths DO work, however I have not been able to figure out why nor replicate it in other projects.
网上有很多帖子详细说明了相对路径如何在 Xcode 中不起作用。我确实有一个 Xcode 模板,我下载了相对路径可以工作的地方,但是我无法弄清楚为什么也无法在其他项目中复制它。
Firstly, I am using C++ in Xcode 3.1. I am not using Objective-C, nor any Cocoa/Carbon frameworks, just pure C++.
首先,我在 Xcode 3.1 中使用 C++。我没有使用 Objective-C,也没有使用任何 Cocoa/Carbon 框架,只是使用纯 C++。
Here is the code that works in my other Xcode template:
这是适用于我的其他 Xcode 模板的代码:
sound->LoadMusic( (std::string) "Resources/Audio/Pop.wav" );
This relative path works for me also in Windows. Running the following command gives me an absolute path to the application's full path:
这个相对路径在 Windows 中也适用于我。运行以下命令为我提供了应用程序完整路径的绝对路径:
std::cout << "Current directory is: " << getcwd( buffer, 1000) << "\n";
/Applications/myApp
/应用程序/我的应用程序
How can we get relative paths to work in an Xcode .app bundle?
我们如何获得在 Xcode .app 包中工作的相对路径?
回答by Brock Woolf
Took me about 5 hours of Google and trying different things to FINALLY find the answer!
花了我大约 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
// ----------------------------------------------------------------------------
I've thrown some extra include guards because this makes it compile Apple only (I develop cross platform) and makes the code nicer.
我抛出了一些额外的包含守卫,因为这使它只能编译 Apple(我开发跨平台)并使代码更好。
I thank the other 2 guys for your answers, your help ultimately got me on the right track to find this answer so i've voted you both up. Thanks guys!!!!
我感谢其他 2 个人的回答,您的帮助最终让我走上了正确的道路,找到了这个答案,所以我已经投票给你们俩了。谢谢你们!!!!
回答by cdespinosa
Do not depend on the current working directory in binary code. Just don't. You cannot trust the operating system or shell to set it to where you expect it to be set, on Mac, Windows, or Unix.
不要依赖于二进制代码中的当前工作目录。只是不要。在 Mac、Windows 或 Unix 上,您不能相信操作系统或 shell 会将其设置为您希望设置的位置。
For straight C, use _NSGetExecutablePath in dyld.h to get the path to your current executable, then you can go relative from there.
对于直 C,在 dyld.h 中使用 _NSGetExecutablePath 来获取当前可执行文件的路径,然后您可以从那里进行相对。
If you're just experimenting and want it to work, in Xcode choose Project > Edit Active Executable, and there's a panel there in which you can set the initial working directory to the project directory, the executable's parent directory, or any arbitrary directory. This should only be used for testing purposes. In the Mac OS, when you write a real app and launch it from the Finder, the working directory is /. And for Unix apps you have no control whatsoever over what the working directory is.
如果您只是在试验并希望它工作,请在 Xcode 中选择 Project > Edit Active Executable,那里有一个面板,您可以在其中将初始工作目录设置为项目目录、可执行文件的父目录或任何任意目录。这应该仅用于测试目的。在 Mac OS 中,当您编写一个真正的应用程序并从 Finder 启动它时,工作目录是 /。对于 Unix 应用程序,您无法控制工作目录是什么。
回答by wisequark
My guess is the type of app you're building is a one-off executable rather than being an executable app-bundle. On OS X and Unixes in general, resources are loaded from the absolute root of the drive which is different than Visual C++'s treatment of "root" being the path relative to project's root. Don't rely on the path ever being relative to anything in particular across OSes (or OS versions for that matter). You can set a working directory in Xcode but that will only impact applications launched from Xcode. If you were to execute it from the build directory in Finder, it'd once again be set to the root of the drive.
我的猜测是您正在构建的应用程序类型是一次性可执行文件,而不是可执行的应用程序包。通常在 OS X 和 Unix 上,资源从驱动器的绝对根加载,这与 Visual C++ 将“根”处理为相对于项目根的路径不同。不要依赖与任何特别是跨操作系统(或操作系统版本)相关的路径。您可以在 Xcode 中设置工作目录,但这只会影响从 Xcode 启动的应用程序。如果您要从 Finder 中的构建目录执行它,它将再次设置为驱动器的根目录。
回答by user250691
Just a comment about relative paths and xcode.
只是关于相对路径和 xcode 的评论。
I recently noticed that if your app has no files which would be copied into the resources folder the current working directory is set to be that of the actual .app - eg at the level of: myApp.app
我最近注意到,如果您的应用程序没有将被复制到资源文件夹中的文件,则当前工作目录将设置为实际 .app 的目录 - 例如在以下级别:myApp.app
However if you add a file to your project and have it copied to the Resources folder of your app bundle it sets the cwd to be 3 levels deep inside the .app. eg at the level of myApp.app/Contents/MacOS/myApp
但是,如果您将文件添加到您的项目并将其复制到您的应用程序包的 Resources 文件夹,它会将 cwd 设置为 .app 内部的 3 个级别。例如在 myApp.app/Contents/MacOS/myApp 级别
It seems xcode is trying to be smart for you and assumes if you have no resources in your app bundle then you would want to be loading files a the .app level and not the internal executables level.
似乎 xcode 正试图让您变得聪明,并假设如果您的应用程序包中没有资源,那么您将希望加载 .app 级别的文件,而不是内部可执行文件级别。
This persists even when the app is launched from the Finder. So maybe another reason to avoid relative paths.
即使从 Finder 启动应用程序,这种情况仍然存在。所以也许是避免相对路径的另一个原因。