在我看来,Linux使用/proc/self/exe很容易但是我想知道是否有一种方便的方法来找到当前应用程序的目录在C/ c++与跨平台接口。我见过一些项目胡乱摆弄argv[0],但它似乎并不完全可靠。
如果你必须支持,比如说,Mac OS X,它没有/proc/,你会怎么做?使用#ifdefs来隔离平台特定的代码(例如NSBundle)?或者尝试从argv[0], $ path和诸如此类的东西中推断可执行文件的路径,冒着在边缘情况下发现错误的风险?
在我看来,Linux使用/proc/self/exe很容易但是我想知道是否有一种方便的方法来找到当前应用程序的目录在C/ c++与跨平台接口。我见过一些项目胡乱摆弄argv[0],但它似乎并不完全可靠。
如果你必须支持,比如说,Mac OS X,它没有/proc/,你会怎么做?使用#ifdefs来隔离平台特定的代码(例如NSBundle)?或者尝试从argv[0], $ path和诸如此类的东西中推断可执行文件的路径,冒着在边缘情况下发现错误的风险?
当前回答
如果你曾经支持过,比如说,麦克 OS X没有/proc/ 你会这么做吗?使用#ifdefs来 隔离特定于平台的代码 (例如NSBundle)?
是的,使用#ifdefs隔离特定于平台的代码是实现这一点的常规方法。
另一种方法是有一个干净的#ifdef-less头,其中包含函数声明,并将实现放在特定于平台的源文件中。
例如,查看POCO(可移植组件)c++库如何为它们的Environment类做类似的事情。
其他回答
在Linux上使用/proc/self/exe或argv[0]的另一种选择是使用ELF解释器传递的信息,由glibc提供:
#include <stdio.h>
#include <sys/auxv.h>
int main(int argc, char **argv)
{
printf("%s\n", (char *)getauxval(AT_EXECFN));
return(0);
}
请注意,getauxval是一个glibc扩展,为了健壮起见,您应该检查它是否返回NULL(表明ELF解释器没有提供AT_EXECFN参数),但我认为这在Linux上实际上从来都不是问题。
您可以使用argv[0]并分析PATH环境变量。 看:一个可以找到自己的程序示例
如果你曾经支持过,比如说,麦克 OS X没有/proc/ 你会这么做吗?使用#ifdefs来 隔离特定于平台的代码 (例如NSBundle)?
是的,使用#ifdefs隔离特定于平台的代码是实现这一点的常规方法。
另一种方法是有一个干净的#ifdef-less头,其中包含函数声明,并将实现放在特定于平台的源文件中。
例如,查看POCO(可移植组件)c++库如何为它们的Environment类做类似的事情。
但是我想知道是否有一种方便的方法来找到当前应用程序的目录在C/ c++与跨平台接口。
你不能这样做(至少在Linux上)
因为一个可执行文件可以,在运行它的进程执行期间,重命名(2)它的文件路径到不同的目录(同一文件系统)。请参见syscalls(2)和inode(7)。
在Linux上,一个可执行文件(原则上)甚至可以通过调用unlink(2)来删除(3)本身。Linux内核应该继续分配该文件,直到没有进程再引用它为止。使用proc(5),你可以做一些奇怪的事情(例如重命名(2)/proc/self/exe文件,等等…)
换句话说,在Linux上,“当前应用程序的目录”的概念没有任何意义。
请参阅高级Linux编程和操作系统:三个简单的部分。
还可以在OSDEV上查看一些开源操作系统(包括FreeBSD或GNU Hurd)。其中一些提供了接近POSIX的接口(API)。
考虑使用(在获得许可的情况下)跨平台c++框架,如Qt或POCO,也许可以通过将它们移植到您喜欢的操作系统来对它们做出贡献。
当然,这并不适用于所有项目。 尽管如此,QCoreApplication::applicationFilePath()在6年的c++ /Qt开发中从未让我失望过。
当然,在尝试使用它之前,应该彻底阅读文档:
警告:在Linux上,此函数将尝试从 /proc文件系统。如果失败,则假定argv[0]包含 可执行文件的绝对文件名。这个函数也假设 应用程序没有更改当前目录。
老实说,我认为#ifdef和其他类似的解决方案根本不应该在现代代码中使用。
我相信更小的跨平台库也存在。让他们把所有特定于平台的东西封装在里面。