2013-04-03 56 views
1

我正在使用C++,flex和GNU bison編寫一個簡單的語言解釋器/轉換器。我需要知道可執行文件的路徑。對於像「mylang mysource.ext」這樣的簡單情況,我可以使用argcargv獲得路徑,但是如果通過shebang調用文件(例如「#/ usr/bin/env mylang」),我該怎麼辦?確定使用C++的可執行文件的路徑

還有其他的情況下,其中argcargv組合將無法正常工作。是否有可能重寫這種情況?如果是這樣,我想獲得可執行文件的完整路徑。解決方案必須是跨平臺的。如果可能的話,我想避免使用外部庫,尤其是boost,這對於我的目標來說是非常大的。謝謝!

+0

在Windows上,'GetModuleFileName(NULL,...)'。 (我懷疑你會發現一個跨平臺的答案。) – RichieHindle 2013-04-03 19:26:21

+3

你使用'argv [0]'會遇到什麼具體問題?您定位的平臺是什麼? – jxh 2013-04-03 19:26:22

+0

相同的主題來了[昨天](http://stackoverflow.com/questions/15776269/how-to-get-apppath-to-executable-files-directory-using-c-language-on-windows-u/ )。通常的解決方案包括argv [0](Linux)或GetModuleFileName()(Windows)。建議:爲什麼不要求用戶定義指向根目錄的$ ENVIRONMENT變量? – paulsm4 2013-04-03 19:26:34

回答

0

這將非常依賴於平臺,但對於Linux,符號鏈接「/ proc/self/exe」指向當前圖像的物理路徑。從這裏,你可以使用readlink來確定路徑。最近,我用這個:

#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string> 
#include <stdexcept> 
#include <boost/scoped_array.hpp> 

std::string path; 

size_t size = 1024; 
const ssize_t err = static_cast<ssize_t>(-1); 
while (true) 
{ 
    boost::scoped_array<char> buffer(new char[size]); 

    ssize_t res = readlink("/proc/self/exe", buffer.get(), size); 

    if (res == err) 
    { 
     if (errno == ENAMETOOLONG) 
      size *= 2; // try again 
     else 
      throw std::runtime_error("unexpected error during readlink"); 
    } 
    else 
    { 
     path.assign(buffer.get(), res); 
     break; 
    } 
} 

這是用G ++ 4.1.2完成的,所以沒有unique_ptr可用,人們也很容易就能刪除到boost::scoped_array參考。

注意:這給出了當前圖像的完整路徑,而不是圖像所在的目錄。要獲取目錄,您需要進行一些操作。 Boost Filesystem也有一些很好的功能來做到這一點。否則,你將不得不自己解析它。

另外,如果你是一個庫,並且不能依賴於改變當前工作目錄的代碼的另一部分,或者無法訪問argv,上述方法非常棒。 getcwd + argv[0]會正常工作當且僅當您可以保證在您的應用程序或庫中沒有任何內容從您的下面更改當前工作目錄(CWD)。 argv[0]只有在CWD不變時纔有效。

此外,如果可執行文件通過環境變量查找la $PATH找到,則需要實現路徑解析以找到您的真實位置。 argv[0]只是返回您啓動的方式。即如果你運行命令「ls -al」,argv[0]到命令「ls」將只是「ls」。如果運行「/ usr/bin/ls -al」,則argv[0]將爲「/ usr/bin/ls」。

相關問題