2011-08-09 49 views
2
執行路徑

比方說我的可執行文件位於/Users/test_user/app在Mac OSX和我從/Users/test_user/Desktop/run_app運行它:C++查找在Mac

Desktop run_app$ /Users/test_user/app/exec 

在我的C++代碼,我怎麼能找到路徑的位置可執行文件(在這種情況下應該是/users/test_user/app)?我需要在代碼中的此路徑中引用一些其他文件,並且不希望在代碼中放置絕對路徑,因爲某些用戶可能會將該文件夾置於其他位置。

+0

這是一個unix可執行文件或.app包嗎? – sbooth

+0

@sbooth unix可執行文件 – ashkash

回答

3

提供我正確認識你,你應該能夠使用NSProcessInfo-arguments方法來獲取可執行文件的路徑。

要將Objective-C代碼與C++代碼混合,只需將源文件的文件擴展名從.cpp更改爲.mm即可。然後將Foundation.framework添加到目標的鏈接庫二進制庫生成階段。

[編輯]更新顯示argv[0][[[NSProcessInfo processInfo] arguments] objectAtIndex:0]之間的差異。

然後使用代碼,你可以做類似下面的代碼:

#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; 
} 

如果我再cd到可執行文件的父目錄,然後使用相對路徑執行可執行文件:

MacPro:~ mdouma46$ cd /Users/mdouma46/Library/Developer/Xcode/DerivedData/executablePath-ewememtbkdajumdlpnciyymduoah/Build/Products/Debug 

MacPro:Debug mdouma46$ ./executablePath blah blah2 

我得到以下輸出:

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 

因此,雖然argv[0]可能不一定是完整路徑,但從[[[NSProcessInfo processInfo] arguments] objectAtIndex:0]返回的結果將是。

所以,有[[[NSProcessInfo processInfo] arguments] objectAtIndex:0],或者稍微簡單的方法就是使用NSBundle本身,即使它是一個命令行工具(見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]; 
+0

我不認爲這是一個可靠的解決方案,因爲argv [0]不保證是絕對路徑。 – sbooth

+0

@sbooth:更新以顯示'Ngr [0]'和'NSProcessInfo'的'-arguments'方法之間的區別。 – NSGod

+0

很高興知道,謝謝。我想知道NSProcessInfo是否僅僅使用了_NSGetExecutablePath。我也很想知道它如何處理符號鏈接和可執行文件已被取消鏈接但仍在運行的情況。但是這些是NSProcessInfo本身不具體的一般問題。 – sbooth

2

man 3 dyld說:

_NSGetExecutablePath()將主可執行文件的路徑複製到 緩衝區buf中。 bufsize參數最初應該是 緩衝區的大小。如果路徑被成功複製,該函數返回0。 如果緩衝區不夠大,它將返回-1,並且* bufsize將 設置爲所需的大小。請注意,_NSGetExecutablePath()將向可執行文件返回「 路徑」,而不是可執行文件的「真實路徑」。即, 該路徑可能是符號鏈接而不是真實文件。深 目錄所需的總bufsize可能會超過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; 
} 
+0

我喜歡這個答案,因爲它適用於任何二進制文件。 –