2

I am trying to load a file with a cocoa app but the app cant find the file

I use SDL_image, the code is:

SDL_Surface* surface = IMG_Load(file);

the file is: "/Resources/cursor.png"

I have tried using some lines in Objective-C but the app won't run since it's written in c++

Thanks, Daniel

Update:

Texture loading code:

GLuint CGLTexture::load_texture(const char* file, bool wrap)
{
SDL_Surface* surface = IMG_Load(file);

if (!surface) {
    printf("Error, probably the file isn't there :S");
    return 0;
}

GLuint texture;
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
SDL_PixelFormat *format = surface->format;

// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// if wrap is true, the texture wraps over at the edges (repeat)
//       ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                wrap ? GL_REPEAT : GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                wrap ? GL_REPEAT : GL_CLAMP );

if (format->Amask)
{
    gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
                      surface->w, surface->h, GL_RGBA,GL_UNSIGNED_BYTE, surface->pixels);
}
else
{
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
                      surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
}
SDL_FreeSurface(surface);
return texture;
}

I call this function like this:

cursorTexture = CGLTexture::load_texture("/Resources/cursor.png",false);

The file is never found, I think this is somewhere in the app's bundle, but, how can i access it with c++?

Daniel Davila
  • 47
  • 1
  • 5

3 Answers3

1

You can use objective-c++, then you have c++ and objective-c features.
To use objetive c in a portable environment use this:

header file:

std::string GetTextureFilename(const char *Name);

implementation file that ends with .mm and included only in mac:

std::string GetTextureFilename(const char *Name)
{
    return [[[NSBundle mainBundle]
                  pathForResource:
                      [NSString stringWithUTF8String: Name
                                              ofType: nil] toUTF8String];
}

source file that ends with .cpp and included only on other platforms:

std::string GetTextureFilename(const char *Name)
{
    return Name;
}
Daniel
  • 30,896
  • 18
  • 85
  • 139
  • It's meant to be a multiplatform app, so, how can I use objective-c++ without changing much of my code? – Daniel Davila Oct 30 '11 at 01:05
  • I created the .h and .mm files, when I include the .h in my cpp file the app wont run, I got errors from NSObjCRuntime.h – Daniel Davila Oct 30 '11 at 01:39
  • @DanielDavila: you shouldn't include anything objective-c related the .h file, only in the .mm file – Daniel Oct 30 '11 at 01:41
  • Parse Issue Expected unqualified -id Parse Issue Unknown type name NSString a lot more like these and Semantic Issue – Daniel Davila Oct 30 '11 at 01:43
  • @DanielDavila: add `#include ` in your **.mm** file – Daniel Oct 30 '11 at 01:44
  • a little bit late, but I got this "warning": `warning: class method '+stringWithUTF8String:ofType:' not found (return type defaults to 'id') [-Wobjc-method-access] [NSString stringWithUTF8String: Name` – somerandomdev49 Mar 25 '20 at 16:14
1

If your code is running from the main application bundle, then you can use the following:

NSString *cursorImagePath = [[NSBundle mainBundle] 
             pathForResource:@"cursor" ofType:@"png"];

const char *cCursorImagePath = [cursorImagePath fileSystemRepresentation];

cursorTexture = CGLTexture::load_texture(cCursorImagePath, false);

(Note: change the filename extension of any files in which you want to use Objective-C from .cpp to .mm).

NSBundle (or CFBundle) can be used to locate the (full) path to resources inside the application bundle. See Bundle Programming Guide: Getting the Path to a Resource.

Also, I'm not sure how "Cocoa" your app is. Specifically, I'm not sure whether you'll already have an NSAutoreleasePool in place. Watch output in Console.app or Xcode's debug console for error messages along the lines of __NSAutoreleaseNoPool() - just leaking. If you do see those, you'll need to surround the above code with the following:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// above code
[pool release];

Regarding "Do I have to include something to use this code? It's a c++ app":

Yes, you'd need to import (and link against if you're not already doing so):

#import <Foundation/Foundation.h>

(#import is Objective-C's smart #include: it assures it's only included once).

You say your app is C++, but the 2 primary GUI frameworks are either Carbon (C-based HIToolbox) or Cocoa (Objective-C based). Do you know which one of those you're using, or are you using another framework (SDL it looks like) which hides those details?

NSGod
  • 22,699
  • 3
  • 58
  • 66
0

Do you mean "./Resources/cursor.png"?

"/Resources/cursor.png" is in the root file system

"./Resources/cursor.png" is relative to the working directory.

or you could do relative to the users home path

#include <string>
#include <stdlib.h>
    std::string filename = getenv("HOME");
    filename += "/.ecf/employee.db";

That won't work on Unix based OSes that don't populate the environment variable. I am told OS X doesn't. Regarless of why it fails you can use getpwuid() at that point.

edit:

Added for completeness. You could base it off the executable's path by using code found here. In all reality almost all of my Unix code bases it off the home directory and fallback to a file found in /etc. That's what most users of my code want( and as a user i want).

Community
  • 1
  • 1
Joe McGrath
  • 1,481
  • 10
  • 26
  • I had this same code running on windows and it was "/Resources/cursor.png" I tried adding the . before / but it has the same problem :( – Daniel Davila Oct 30 '11 at 00:37
  • @DanielDavila I was guessing you were using a unix varient because your slashes were forward (/). What OS is the code now suppose to run on? Are you running this from an IDE? if so your working directory may no be where you think it is. That is normally the issue with Windows version. Try running from the directory you want it to be relative to and with "./" – Joe McGrath Oct 30 '11 at 00:44
  • I'm using OSX, the code you published didn't work. The IDE is Xcode. The app is a simple game and it should be multiplatform. – Daniel Davila Oct 30 '11 at 00:50
  • Outside of my territory. Don't know anything about OSX. I would start with a google of NSHomeDirectory() and see where that gets you. _I just want to mention running the exe from the folder it is in again. there is a good chance your IDE is running it from the Project or Solution's directory_ – Joe McGrath Oct 30 '11 at 00:54
  • @JoeMcGrath: there is no exe in Mac. the equivalent of "program" in mac is a sort of directory, but you can't change the contents of the working directory (a subdirectory inside of the "program" directory) – Daniel Oct 30 '11 at 01:23