|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| Something like GetModuleFileName in Linux? |
|
![]() Foxostro Member since: 7/23/2003 From: Pittsburgh, USA |
||||
|
|
||||
| Is there a portable way to do the equivalent of GetModuleFileName(0) in Linux? I was working on a game with some friends over the Spring. Now, I'm porting it to Linux, but I've run into a snag. I need to be able to find the directory where the executable is actually located, which I can accomplish easily in Windows with a call to GetModuleFileName(0). In Linux, I thought I could use argv[0] instead, but I've read that this is unreliable at best. |
||||
|
||||
![]() hydroo Member since: 10/26/2006 |
||||
|
|
||||
| Well I personally would use argv[0]. If argv[0] appears to be a relative path you have to merge it with getcwd() ( your current working directory ) Maybe some of your libraries already provide the functionality for doing paths or even getting the full executable name, otherwise you might have to translate the relativ path by hand. -- Is it really necessary? |
||||
|
||||
![]() let_bound Member since: 8/9/2006 |
||||
|
|
||||
There is no portable, reliable way to do that. Just as you wouldn't like a game storing its data in C:\usr\local\games\the-game on Windows, GNU/Linux users find it annoying when a program tries to behave like it's on Windows. There is a filesystem hierarchy, use it. Your application should behave properly, and not try to force the user to accept a behaviour alien to her system.Quote:
$ cat foo.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("%s\n", argv[0]);
return 0;
}
$ make foo
$ /home/username/foo
/home/username/foo
$ mkdir somedir
$ cd somedir
$ ln -s ../foo bar
$ /home/username/somedir/bar
/home/username/somedir/bar
Links are so common on UN*X systems you definitely can't count on them not being used. There is one way to get such information on GNU/Linux that I know of, but it isn't portable to non-Linux systems (BSD, Solaris), and it requires a /proc filesystem (which a lot of GNU/Linux systems have, but not all do):
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char path[256];
char id[256];
sprintf(id, "/proc/%d/exe", getpid());
readlink(id, path, 255);
path[255] = '\0';
printf("%s\n", path);
return 0;
}
Unstested. You'll want something else than 256 there, and I'm not so sure about readlink(2)'s behaviour wrt the nul character. Hope this helps. |
||||
|
||||
![]() eedok Member since: 9/15/2003 From: Edmonton, Canada |
||||
|
|
||||
| Boost::FileSystem may have what you need. |
||||
|
||||
![]() Foxostro Member since: 7/23/2003 From: Pittsburgh, USA |
||||
|
|
||||
Quote: Ideally, I would like the game to be completely apathetic to where it is installed. Are you suggesting that I should avoid assuming that the executable is anywhere near the game's data? (Say, if game data was stored in /usr/local/share and the executable in /usr/local/bin) I'm already assuming that its OK to write data files like saved games and configuration settings to /home/user-name/.my-game's-name/ If this actually is acceptable, then maybe I'll just ask the user during installation what paths are appropriate and keep them in my setup.ini file. |
||||
|
||||
![]() let_bound Member since: 8/9/2006 |
||||
|
|
||||
Quote: Yes. Game data on UN*X-like systems is typically stored in /usr(/local)/share/games/game_name, while the program is often stored in /usr(/local)/games/game_name, with a symlink in /usr(/local)/bin to the main executable(s). It's also possible to have a non-FHS program in /opt, but I'd like to suggest not going that way unless you have very specific needs (see Wikipedia, keeping in mind that not everything applies... You'll need a bit of GNU/Linux culture here I'm afraid ).Quote: That's the Right Way to do it, as far as storage is concerned. For your game to locate data, you'll usually do something like this:
|
||||
|
||||
![]() benacler Member since: 8/24/2007 From: Roma, Italy |
||||
|
|
||||
| This is what you're asking for Linux and Darwin, on Linux it uses the /proc filesystem... #ifdef MAC std::string get_basepath() { std::string path = "./"; ProcessSerialNumber PSN; ProcessInfoRec pinfo; FSSpec pspec; FSRef fsr; OSStatus err; /* set up process serial number */ PSN.highLongOfPSN = 0; PSN.lowLongOfPSN = kCurrentProcess; /* set up info block */ pinfo.processInfoLength = sizeof(pinfo); pinfo.processName = NULL; pinfo.processAppSpec = &pspec; /* grab the vrefnum and directory */ err = GetProcessInformation(&PSN, &pinfo); if (! err ) { char c_path[2048]; FSSpec fss2; int tocopy; err = FSMakeFSSpec(pspec.vRefNum, pspec.parID, 0, &fss2); if ( ! err ) { err = FSpMakeFSRef(&fss2, &fsr); if ( ! err ) { char c_path[2049]; err = (OSErr)FSRefMakePath(&fsr, (UInt8*)c_path, 2048); if (! err ) { path = c_path; } } } } return (path); } #endif #ifdef LINUX std::string get_basepath() { std::string path = ""; pid_t pid = getpid(); char buf[10]; sprintf(buf,"%d",pid); std::string _link = "/proc/"; _link.append( buf ); _link.append( "/exe"); char proc[512]; int ch = readlink(_link.c_str(),proc,512); if (ch != -1) { proc[ch] = 0; path = proc; std::string::size_type t = path.find_last_of("/"); path = path.substr(0,t); } return (path); } #endif |
||||
|
||||
![]() Sander Moderator - Web Development Member since: 4/19/2002 From: Den Bosch, Netherlands |
||||
|
|
||||
| @benacler: Try wrapping your code in [source][/source] tags to preserve formatting, do highlighting, etcetera. See the forum FAQ. Sander Maréchal [Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ] |
||||
|
||||
![]() Umesh G Tank Member since: 8/31/2007 From: Ahmedabad, India |
||||
|
|
||||
| Hi, Boost filesystem provides portable way of getting the current file path. boost::filesystem::path curPath = boost::filesystem::current_path(); std::string strPath = curPath.string(); std::cout<<strPath; this will give you the current directory path. hope that it will help you. Tank |
||||
|
||||
![]() Null and Void Moderator - Everything Unix Member since: 9/7/2000 From: Aurora, CO, United States |
||||
|
|
||||
Quote: Which isn't really a solution to Foxostro's problem, since the current path may be a different one from where the executable is located. Boost's filesystem does offer an initial_path function, but it is not guaranteed to work on all platforms (it may just return the current path at the time of its first execution, if I recall correctly). I recommend following let_bound's advice and taking the few minutes to understand and utilize the at-first disorienting *nix filesystem arrangement. |
||||
|
||||
![]() Raptor85 GDNet+ Member since: 8/21/2002 From: Lake Hughes, CA, United States |
||||
|
|
||||
| Don't know if you're talking about game data as in your resources, or game data as in user preferences, etc.. but any user preference files, configuration files, etc... it's most "friendly" to store in ~/.(yourgamename)/ |
||||
|
||||
![]() Umesh G Tank Member since: 8/31/2007 From: Ahmedabad, India |
||||
|
|
||||
| I am not very much sure that the boost::filesystem will solve Foxostro's problem. but i am sure with the code that was there in the previous post will behave similar to GetModuleFileName in windows. I also need the same api that will work cross platform and i wrote a simple sample application. if i will put that exe in different drive (e.g c:\ in windows) then it was giving me correct path. i put that exe in different drives and folder but each time i got the correct path information, if i am not wrong then thats what GetModuleFileName is doing. That sample is very very simple even though if anybody wants that i will be happy to share it too.... :-). i am sorry if i am going out of track Umesh |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|