在我看来,Linux使用/proc/self/exe很容易但是我想知道是否有一种方便的方法来找到当前应用程序的目录在C/ c++与跨平台接口。我见过一些项目胡乱摆弄argv[0],但它似乎并不完全可靠。

如果你必须支持,比如说,Mac OS X,它没有/proc/,你会怎么做?使用#ifdefs来隔离平台特定的代码(例如NSBundle)?或者尝试从argv[0], $ path和诸如此类的东西中推断可执行文件的路径,冒着在边缘情况下发现错误的风险?


当前回答

Gregory Pakosz的whereami库使用mark4o文章中提到的api为各种平台实现了这一点。如果您“只是”需要一个适用于可移植项目的解决方案,而对各种平台的特性不感兴趣,那么这是最有趣的。

在撰写本文时,受支持的平台有:

窗户 Linux Mac iOS 安卓 QNX Neutrino FreeBSD NetBSD 蜻蜓BSD SunOS

该库由whereami.c和whereami.h组成,并在MIT和WTFPL2下获得许可。将文件放入您的项目中,包括头文件并使用它:

#include "whereami.h"

int main() {
  int length = wai_getExecutablePath(NULL, 0, NULL);
  char* path = (char*)malloc(length + 1);
  wai_getExecutablePath(path, length, &dirname_length);
  path[length] = '\0';

  printf("My path: %s", path);

  free(path);
  return 0;
}

其他回答

除了mark4o的答案,FreeBSD也有

const char* getprogname(void)

它应该也可以在macOS中使用。它可以通过libbsd在GNU/Linux中获得。

Gregory Pakosz的whereami库使用mark4o文章中提到的api为各种平台实现了这一点。如果您“只是”需要一个适用于可移植项目的解决方案,而对各种平台的特性不感兴趣,那么这是最有趣的。

在撰写本文时,受支持的平台有:

窗户 Linux Mac iOS 安卓 QNX Neutrino FreeBSD NetBSD 蜻蜓BSD SunOS

该库由whereami.c和whereami.h组成,并在MIT和WTFPL2下获得许可。将文件放入您的项目中,包括头文件并使用它:

#include "whereami.h"

int main() {
  int length = wai_getExecutablePath(NULL, 0, NULL);
  char* path = (char*)malloc(length + 1);
  wai_getExecutablePath(path, length, &dirname_length);
  path[length] = '\0';

  printf("My path: %s", path);

  free(path);
  return 0;
}

一些特定于操作系统的接口:

Mac OS X: _NSGetExecutablePath() (man 3 dyld) Linux: readlink /proc/self/exe Solaris: getexecname () sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1 readlink /proc/curproc/file (FreeBSD默认没有procfs) NetBSD: readlink /proc/curproc/exe DragonFly BSD: readlink /proc/curproc/file Windows: GetModuleFileName() with hModule = NULL

也有第三方库可以用来获取这些信息,比如在prideout的回答中提到的whereami,或者如果你使用Qt,评论中提到的QCoreApplication::applicationFilePath()。

可移植的(但不太可靠)方法是使用argv[0]。尽管调用程序可以将它设置为任何东西,但按照惯例,它要么被设置为可执行文件的路径名,要么被设置为使用$ path找到的名称。

一些shell,包括bash和ksh,在执行可执行文件之前将环境变量“_”设置为可执行文件的完整路径。在这种情况下,您可以使用getenv("_")来获取它。然而,这是不可靠的,因为不是所有的shell都这样做,并且它可以被设置为任何东西,或者是在执行程序之前没有更改它的父进程遗留下来的。

如果你曾经支持过,比如说,麦克 OS X没有/proc/ 你会这么做吗?使用#ifdefs来 隔离特定于平台的代码 (例如NSBundle)?

是的,使用#ifdefs隔离特定于平台的代码是实现这一点的常规方法。

另一种方法是有一个干净的#ifdef-less头,其中包含函数声明,并将实现放在特定于平台的源文件中。

例如,查看POCO(可移植组件)c++库如何为它们的Environment类做类似的事情。

您可以使用argv[0]并分析PATH环境变量。 看:一个可以找到自己的程序示例