如何使用独立于平台的方法获取 C 中执行程序的目录?

发布于 2024-09-05 06:05:18 字数 164 浏览 12 评论 0原文

我在 Linux 上为 unix 和 win32(在每个构建时交叉编译)平台开发我的应用程序,所以一个随时可用的函数会很好:)。我使用的 glib 具有 gchar* g_get_current_dir(void) 函数,它返回当前目录,但我真正需要的是可执行文件的目录。我对 C 编程缺乏经验,所以欢迎任何建议。

I develop my app in Linux for both unix and win32(cross compile at each build) platforms, so a ready to use function would be nice :). I'm using glib that has the gchar* g_get_current_dir(void) function and it returns the current directory, but what I really need is the executable's directory. I'm inexperienced in C programming so any suggestions are welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小清晰的声音 2024-09-12 06:05:18

在具有 /proc 目录的类 Unix 操作系统下,您可以 readlink /proc/self/exe 获取实际可执行文件的完整路径,甚至当argv[0]没有这个时。

但是,如果可执行文件是用 fexecv 启动的(在许多系统上不可用)并且在您的系统上作为系统调用实现,则这可能不起作用。 fexecvexecve 类似,只不过它传递的是打开的文件描述符而不是要运行的文件名。在 Linux 下,它是通过对 `"/proc/self/%i", fd" 生成的字符串调用 execve 来实现的,因此该文件必须在程序运行时存在于文件系统中 我认为

GNU/Hurd 本身支持 fexecve

可执行文件在执行后可能会被重命名或从文件系统中取消链接,这使其成为一个未命名的文件。一旦它停止打开(在这种情况下运行文件通常需要它被内核打开),它就会消失。

Under Unix like operating systems that have the /proc directory you can readlink /proc/self/exe to get the actual executable files full path even when argv[0] does not have this.

This may not work, however, if the executable was started with fexecv (not available on many systems) and if that is implemented as a system call on your system. fexecv is just like execve except that it is passed an open file descriptor rather than a filename to run. Under Linux it is implemented by calling execve on the string generated by `"/proc/self/%i", fd", so the file would have to live in the file system at the time the program was started.

I think that GNU/Hurd supports fexecve natively.

It is possible for an executable file to be renamed or unlinked from the filesystem after it has been executed which makes it become an unnamed file which will go away as soon as it ceases to be open (in this context running a file usually requires it to be open by the kernel).

绾颜 2024-09-12 06:05:18

Windows 中的 GetModuleFileName
Linux 中的 argv[0]

注意: 如果你进行跨平台编程,你还应该使用一些隐藏这一层的跨平台库(Qt、wxWidgets、ACE、Boost[不知道,但我认为它有一些东西]...)

GetModuleFileName in Windows.
argv[0] in linux

NOTE: If you do cross-platform programming you should use also some cross platform libraries that hide this layer (Qt, wxWidgets, ACE, Boost[Don't know but I think it has something] ... )

笙痞 2024-09-12 06:05:18

我无法与窗户交谈。然而,在 UNIX 中,相当一部分时间是可能的,但不能保证。其原因涉及从其他程序(例如 shell)调用 exec,在某些情况下,这可能会使可执行文件所在的位置变得模糊,例如,像“../../../mybin/exe/myprogram”这样的相对路径。 PATH 变量还使得追踪可执行文件变得很有趣。

让我问:你想做什么,或者更正确地说,你为什么需要知道?
IMO你不需要知道。您可以检查 getcwd() ,如果您没有在有效的目录中运行,请退出。可执行映像位于何处并不重要。

这是一个在大多数情况下都有效的代码块,但并非总是如此!

需要从 main 调用,使用 argv[0],我使用 popen() 调用 shell 来使代码适合一个小区域,popen() 并不总是一个很好的选择,如果之前有其他可执行文件,这可能会失败在具有相同名称的 PATH 中:

char *
mypath(const char *src)
{
   FILE *cmd=NULL;
   static char path_2_me[PATH_MAX]={0x0};
   char tmp[PATH_MAX]={0x0};
   const char *basename=strrchr(src, '/');

   if(basename==NULL) 
        basename=src;
   else
        basename++;      

   if(memcmp(src, "./", 2)==0)      
     sprintf(path_2_me,"%s/%s", getcwd(tmp, PATH_MAX), basename);             
   else
   {
      sprintf(tmp, "/usr/bin/which %s", basename);
      cmd=popen(tmp, "r");      
      fgets(path_2_me, sizeof(path_2_me), cmd); /* one read only */
      pclose(cmd);
      /* check for what your version of which says on failure */
      if(memcmp(path_2_me, "no ", 3)==0)
         *path_2_me=0x0;
   }  

   return (*path_2_me) ?path_2_me: NULL;
}

I cannot speak to windows. However in UNIX, a fair percentage of the time it is possible, but it is not guaranteed. The reasons for this involve calls to exec from other programs like shell which in some circumstances can cloud where the executable lives, for example, a relative path like "../../../mybin/exe/myprogram". The PATH variable also makes it fun to track down an executable.

Let me ask: what are you trying to do, or, more correctly, why do you need to know?
IMO you don't need to know. you can check getcwd() and if you are not running in a directory that works, exit. It should not matter where your executable image lives.

Here is one code hunk that works most of the time, not always!

requires a call from main, using argv[0], I am using popen() calls to shell to make the code fit in a small are, popen() is not always a great choice, this can fail if there are other executables earlier in the PATH with the same name:

char *
mypath(const char *src)
{
   FILE *cmd=NULL;
   static char path_2_me[PATH_MAX]={0x0};
   char tmp[PATH_MAX]={0x0};
   const char *basename=strrchr(src, '/');

   if(basename==NULL) 
        basename=src;
   else
        basename++;      

   if(memcmp(src, "./", 2)==0)      
     sprintf(path_2_me,"%s/%s", getcwd(tmp, PATH_MAX), basename);             
   else
   {
      sprintf(tmp, "/usr/bin/which %s", basename);
      cmd=popen(tmp, "r");      
      fgets(path_2_me, sizeof(path_2_me), cmd); /* one read only */
      pclose(cmd);
      /* check for what your version of which says on failure */
      if(memcmp(path_2_me, "no ", 3)==0)
         *path_2_me=0x0;
   }  

   return (*path_2_me) ?path_2_me: NULL;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文