2013-04-03 13 views
1

Я пишу простой переводчик/переводчик с использованием C++, flex и GNU bison. Мне нужно знать путь к исполняемому файлу. Для простых случаев, таких как «mylang mysource.ext», я могу получить путь, используя argc и argv, но что делать, если файл вызывается через shebang (например, «#/usr/bin/env mylang»)?Определить путь к исполняемому с помощью C++

Другие случаи, когда argc и argv комбинация не работает. Можно ли переопределить такие ситуации? Если это так, я хотел бы получить полный путь к исполняемому файлу. Решение должно быть кросс-платформенным. Если возможно, я бы хотел избежать использования внешних библиотек, особенно повышения, что чрезвычайно важно для моих целей. Благодаря!

+0

В Windows, 'GetModuleFileName (NULL, ...)'. (Я сомневаюсь, что вы найдете один кросс-платформенный ответ.) – RichieHindle

+3

С какими конкретными проблемами вы сталкиваетесь с использованием 'argv [0]'? На каких платформах вы нацеливаетесь? – jxh

+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

ответ

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 не изменился.

Кроме того, если исполняемый файл находится через поиск переменных окружения a la $PATH, вам необходимо реализовать разрешение пути, чтобы найти, где вы на самом деле находитесь. argv[0] просто возвращает то, как вы были запущены. т. е. если вы выполнили команду «ls -al», то argv[0] команде «ls» будет просто «ls». Если вы запустили «/ usr/bin/ls -al», argv[0] будет «/ usr/bin/ls».

Смежные вопросы