问题
Lets say my executable is located at /Users/test_user/app
on Mac OSX and I am running it from /Users/test_user/Desktop/run_app
:
Desktop run_app$ /Users/test_user/app/exec
Within my C++ code how can I find the path to the location of the executable (which in this case would be /users/test_user/app
)? I need to reference some other files at this path within my code and do not want to put absolute paths within the code as some users might place the folder in a different location.
回答1:
man 3 dyld
says:
_NSGetExecutablePath() copies the path of the main executable into the buffer buf. The bufsize parameter should initially be the size of the buffer. This function returns 0 if the path was successfully copied. It returns -1 if the buffer is not large enough, and * bufsize is set to the size required. Note that _NSGetExecutablePath() will return "a path" to the executable not a "real path" to the executable. That is, the path may be a symbolic link and not the real file. With deep directories the total bufsize needed could be more than MAXPATHLEN.
#include <mach-o/dyld.h>
#include <limits.h>
int main(int argc, char **argv)
{
char buf [PATH_MAX];
uint32_t bufsize = PATH_MAX;
if(!_NSGetExecutablePath(buf, &bufsize))
puts(buf);
return 0;
}
回答2:
Provided I'm understanding you correctly, you should be able to use NSProcessInfo
's -arguments method to get the executable path.
To mix in Objective-C code with C++ code, you can just change the filename extension of the source file in question from .cpp to .mm. Then add the Foundation.framework to the Link Binary With Library build phase of your Target.
[EDIT] updated to show the difference between argv[0]
and [[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
.
Then to use the code, you could do something like in the following code:
#include <iostream>
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// print out raw args
NSMutableArray *arguments = [NSMutableArray array];
for (NSUInteger i = 0; i < argc; i++) {
NSString *argument = [NSString stringWithUTF8String:argv[i]];
if (argument) [arguments addObject:argument];
}
NSLog(@"arguments == %@", arguments);
const char *executablePath =
[[[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
fileSystemRepresentation];
printf("executablePath == %s\n", executablePath);
const char *executableDir =
[[[[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
stringByDeletingLastPathComponent] fileSystemRepresentation];
printf("executableDir == %s\n", executableDir);
[pool release];
return 0;
}
If I then cd
into the parent directory of the executable, and then execute the executable using a relative path:
MacPro:~ mdouma46$ cd /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug
MacPro:Debug mdouma46$ ./executablePath blah blah2
I get the following output:
2011-08-10 12:59:52.161 executablePath[43554:707] arguments == (
"./executablePath",
blah,
blah2
)
executablePath == /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug/executablePath
executableDir == /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug
So, while argv[0]
may not necessarily be a full path, the result returned from [[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
will be.
So, there's [[[NSProcessInfo processInfo] arguments] objectAtIndex:0]
, or a slightly simpler approach is just to use NSBundle
itself, even if it is a command-line tool (see What is the "main bundle" of a command-line foundation tool?):
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
const char *executablePath =
[[[NSBundle mainBundle] executablePath] fileSystemRepresentation];
[pool release];
回答3:
Maybe you could use the which
command. http://unixhelp.ed.ac.uk/CGI/man-cgi?which
回答4:
If it's a "real" OS X application the proper way to do it is to create a bundle:
http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFBundleRef/Reference/reference.html
来源:https://stackoverflow.com/questions/7004401/c-find-execution-path-on-mac