argv[0]
現在のプロセスをロードするシェルコマンドを参照します。getcwd()
現在の作業ディレクトリに戻ります。この情報を使用して、プログラムのバイナリ実行可能ファイルへの絶対パスを設定できますか?プログラムがcd
最初にロードされてからすでに完了している場合は、機能しないことを願っています。
答え1
プログラミング言語インタプリタ内で、次のコードを使用して独自のパスを取得します。
Linux、Windows(Cygwinを含む)、Mac、およびSolaris用の特別なコードがあります。
#if __APPLE__
#include <mach-o/dyld.h>
#endif
#if __linux__
static val get_self_path(void)
{
char self[PATH_MAX] = { 0 };
int nchar = readlink("/proc/self/exe", self, sizeof self);
if (nchar < 0 || nchar >= convert(int, sizeof self))
return nil;
return string_utf8(self);
}
#elif HAVE_WINDOWS_H
static val get_self_path(void)
{
wchar_t self[MAX_PATH] = { 0 };
DWORD nchar;
SetLastError(0);
nchar = GetModuleFileNameW(NULL, self, MAX_PATH);
if (nchar == 0 ||
(nchar == MAX_PATH &&
((GetLastError() == ERROR_INSUFFICIENT_BUFFER) ||
(self[MAX_PATH - 1] != 0))))
return nil;
return string(self);
}
#elif __APPLE__
static val get_self_path(void)
{
char self[PATH_MAX] = { 0 };
uint32_t size = sizeof self;
if (_NSGetExecutablePath(self, &size) != 0)
return nil;
return string_utf8(self);
}
#elif HAVE_GETEXECNAME
static val get_self_path(void)
{
val execname = string_utf8(getexecname());
if (car(execname) == chr('/'))
return execname;
return scat3(getcwd_wrap(), chr('/'), execname);
}
#else
static val get_self_path(void)
{
char self[PATH_MAX];
if (argv[0] && realpath(argv[0], self))
return string_utf8(self);
return lit(HARD_INSTALLATION_PATH);
}
#endif
型val
、記号、nil
関数はインタプリタの内側にあります。ただの抽象キャストマクロです。もちろん、いくつかのヘッダファイルも必要です。string
string_utf8
convert
readlink
realpath
このgetexecname
機能はSolarisのものです。何らかの理由で絶対パスを取得するには、現在のディレクトリを貼り付ける必要がある相対パスを処理する状況でコーディングしているようです。
代替戦略は、argv[0]
fromがmain
利用可能な場合にrealpath
それを呼び出して実行することです。使用できない場合は、argv[0]
変数のハードコードされたインストールパスを使用してくださいMakefile
。たとえば、プログラムがとしてインストールされている場合、/usr/bin/foo
レシピMakefile
はそれをコンパイラのコマンドラインに挿入します-DHARD_INSTALLATION_PATH=/usr/bin/foo
。もちろん、プログラムがビルドパスにインストールされている場合にのみ当てはまります。
答え2
Linuxではシンボリックリンクを使用できます/proc/self/exe
$ ls -l /proc/self/exe
lrwxrwxrwx 1 rudi users 0 2016-10-18 16:20 /proc/self/exe -> /usr/bin/ls