実装例は https://github.com/cielavenir/7bgzf/blob/master/lib/getmodulefilename.c にあるんですが、まとめ的なものを書いていなかった。1
Windows
Windowsの当該関数のクローンを作るって言うんだからWindowsでは当然ながらGetModuleFileNameで良い
ハンドルがNULLの場合
プロセス本体のパスを返す仕様になっている。
macOS2
_NSGetExecutablePathを使う。
Solaris
getexecnameを使う(らしい)
FreeBSD
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
size_t bufsize = nSize-1;
if(sysctl(mib, 4, pFilename, &bufsize, NULL, 0)<0){
return 0;
}
// pFilename
Linux
readlink("/proc/self/exe")
NetBSD
readlink("/proc/curproc/exe")
OpenBSD
readlink("/proc/curproc/file")
ハンドルが非NULLの場合
macOS
_dyld_image_count()分_dyld_get_image_name(i)することでimage_nameを列挙。dlopenして、与ハンドルと同じか見る
Android
dlinfo関数が使えない。
/proc/self/map_filesディレクトリを列挙する、もしくは/proc/self/mapsファイルを開いて、image_nameを列挙。dlopenして、与ハンドルと同じか見る
Linux / FreeBSD / NetBSD/ OpenBSD/ Soralis
struct link_map *lm=NULL;
dlinfo(hModule, RTLD_DI_LINKMAP, &lm);
// lm->l_name
ところでp7zipってどんなことやってるんだろうなと思いましたが、https://github.com/p7zip-project/p7zip/blob/master/CPP/7zip/UI/Common/ArchiveCommandLine.cpp によると7z.exeと7z.soが同じディレクトリに存在することを仮定しているようですね…
(/usr/bin/7zの実体が/usr/lib/p7zip/7zに置かれている理由の一つでもある)