Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

RedBull27

macrumors newbie
Original poster
May 13, 2008
8
0
Hi,

I have written code using Visual Studio 6 under XP and i'm trying to port the code to Mac OS X under Xcode. I've narrowed my problem down to the fact that the compiled application under Xcode appears to convert my relative paths to absolute paths, which strangely enough default to the home folder.
:mad:

Code:
char fileCarpetBlue128[40] = "CarpetTexture-128.raw";
The above code under Windows will load the texture as long as it is in the same directory as the .exe file.

However under Mac OS X 10.5 with Xcode 3.0, it will try to load the folder from the home directory. eg: ~/CarpetTexture-128.raw

I discovered this was happening by using this:
Code:
printf("cwd is: %s\n", getcwd(NULL, 0));

Can someone please tell me how to force the path to be relative to the application under OS X.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
Go to developer.apple.com. Type "bundle" into the search field. The first link is most likely "Bundle Programming Guide: Introduction to Bundle Programming Guide". Click on the link.

This lets you find resources relative to the application bundle, automatically finding the right resource depending on the user's language when needed.
 

RedBull27

macrumors newbie
Original poster
May 13, 2008
8
0
Go to developer.apple.com. Type "bundle" into the search field. The first link is most likely "Bundle Programming Guide: Introduction to Bundle Programming Guide". Click on the link.

This lets you find resources relative to the application bundle, automatically finding the right resource depending on the user's language when needed.

I did that. I can and do not want to use bundles for what should be a simple problem. I don't need to do localization and I am using C. From what I could see bundles are Objective-C specific and the code I am writing needs to be cross-platform.

This is for a university project. Maybe I should just stick with Visual Studio and Windows. It seems to be much more straight forward in this regard.
 

yeroen

macrumors 6502a
Mar 8, 2007
944
2
Cambridge, MA
This has nothing to do with Xcode, but rather the POSIX specification. When you call getcwd(), it's returning the path that the executable file was run from. So if you're in your home directory, getcwd() will return the path of your home directory. If you 'cd' to the /etc directory (leaving your executable where it is) and run your program again, getcwd() will return '/etc'.

If you want to set the working directory relative to the executable path, the trick is to use argv[0], which is always the path of the executable.

chdir( argv[0] );


For example, try compiling and running this simple program:

Code:
/* 
 * path.c
 */
#include <stdio.h>
#include <unistd.h>

int main (int argc, char **argv)
{
  printf("%s\n", getcwd(NULL, 0));
  printf("%s\n", chdir(argv[0]));
  printf("%s\n", getcwd(NULL, 0));
}

Far from being straightforward, Windows' POSIX non-conformance makes it the odd-man out in this regard.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
If you want to set the working directory relative to the executable path, the trick is to use argv[0], which is always the path of the executable.

Only if argc > 0, which is not guaranteed, depending on how the application is started. If argc == 0, then argv[0] is not defined.
 

yeroen

macrumors 6502a
Mar 8, 2007
944
2
Cambridge, MA
argc is always greater than or equal to one, since argv[0], being implicit, is always there. If it wasn't, you'd have no program running in the first place.
 

Krevnik

macrumors 601
Sep 8, 2003
4,101
1,312
I did that. I can and do not want to use bundles for what should be a simple problem. I don't need to do localization and I am using C. From what I could see bundles are Objective-C specific and the code I am writing needs to be cross-platform.

If this is a GUI app on OS X, it will be in a bundle, C or not. Carbon just has a different mechanism for getting at the bundle path (CFBundle APIs).

In the case of OS X, it is assumed that all your resources (images, strings, etc) are in the bundle rather than floating about the file system. The intent is that if someone wants to drag your app around to a new location, copy it to a different machine, it will just work.

If you are in the command-line environment, you need to approach development on the Mac like BSD/Linux/POSIX, rather than Windows, as commented earlier.

This is for a university project. Maybe I should just stick with Visual Studio and Windows. It seems to be much more straight forward in this regard.

Will the individuals running this be on Windows-only? Then it might be. Cross-platform apps are never as simple as they first appear, especially when you are first delving into cross-platform development. There are a lot of gotchas like these floating around that you need to consider when writing for more than one platform.
 

RedBull27

macrumors newbie
Original poster
May 13, 2008
8
0
Thank you Yeroen,

What you've said makes the most sense to me although I would like to thank everyone else for your responses.
Okay so I get it that Windows is non-standard (no surprises there :) ) however I did try what you said.

I did:
Code:
  printf("%s\n", getcwd(NULL, 0));
  printf("%s\n", chdir(argv[0]));
  printf("%s\n", getcwd(NULL, 0));

From a different file (im not running the code inside the main file)
and it said it could not find argv[0]. It was 'undefined'.

So I guess the scope of argv and argc is inside main only. Is there another way I could access argv[0] outside of main,
besides copying its string into a global variable? Thanks


This has nothing to do with Xcode, but rather the POSIX specification. When you call getcwd(), it's returning the path that the executable file was run from. So if you're in your home directory, getcwd() will return the path of your home directory. If you 'cd' to the /etc directory (leaving your executable where it is) and run your program again, getcwd() will return '/etc'.

If you want to set the working directory relative to the executable path, the trick is to use argv[0], which is always the path of the executable.

chdir( argv[0] );


For example, try compiling and running this simple program:

Code:
/* 
 * path.c
 */
#include <stdio.h>
#include <unistd.h>

int main (int argc, char **argv)
{
  printf("%s\n", getcwd(NULL, 0));
  printf("%s\n", chdir(argv[0]));
  printf("%s\n", getcwd(NULL, 0));
}

Far from being straightforward, Windows' POSIX non-conformance makes it the odd-man out in this regard.
 

Nutter

macrumors 6502
Mar 31, 2005
432
0
London, England
So I guess the scope of argv and argc is inside main only. Is there another way I could access argv[0] outside of main,
besides copying its string into a global variable?

Yes, the scope of any function argument in C is limited to within the function itself. By all means, copy it to a global variable in main().

You can also use ProcessInformationCopyDictionary() to get at this information.
 

yeroen

macrumors 6502a
Mar 8, 2007
944
2
Cambridge, MA
Well, you don't have to put the pathname into a global variable, although there is nothing wrong (however unfashionable) with declaring such a variable, assign to it the contents of argv[0] in main(), and declaring it as an 'extern' variable in your other files which reference it.

But unless your code is calling chdir() multiple times, declaring a global variable to set the relative path is unecessary. It is sufficient to call chdir() once in main() and be done with it for the duration of your program.

One thing you will have to do, which I forgot to mention before, is to strip off the executable name from argv[0], i.e. everything to the right of the last "/", so you get the directory it's in rather than the executable itself.
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
I know I'm being pedantic but argc is not guaranteed to be > 0. For example, execl( argv[ 0 ], 0L ) will run a copy of itself but without any arguments.

b e n
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.