【问题标题】:Relative path for files in c++ app using xcode使用xcode的c ++应用程序中文件的相对路径
【发布时间】:2011-12-18 01:25:25
【问题描述】:

我正在尝试使用可可应用加载文件,但该应用无法找到该文件

我用的是SDL_image,代码是:

SDL_Surface* 表面 = IMG_Load(file);

文件是:“/Resources/cursor.png”

我尝试在 Objective-C 中使用一些代码,但应用程序无法运行,因为它是用 c++ 编写的

谢谢, 丹尼尔

更新:

纹理加载代码:

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;
}

我这样称呼这个函数:

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

该文件永远找不到,我认为这是应用程序包中的某个位置,但是,我如何使用 c++ 访问它?

【问题讨论】:

  • 相关代码和错误信息?
  • 嘿,我已经更新了问题,提供了有关问题的更多信息,谢谢^^

标签: c++ xcode cocoa sdl


【解决方案1】:

你可以使用objective-c++,那么你就有c++和objective-c的特性了。
要在可移植环境中使用目标 c,请使用:

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;
}

【讨论】:

  • 它是一个多平台应用程序,那么,如何在不更改大部分代码的情况下使用objective-c++?
  • 我创建了 .h 和 .mm 文件,当我在我的 cpp 文件中包含 .h 时应用程序无法运行,我从 NSObjCRuntime.h 收到错误
  • @DanielDavila:你不应该在.h文件中包含任何与objective-c相关的东西,只在.mm文件中
  • 解析问题预期不合格 -id 解析问题未知类型名称 NSString 更像这些和语义问题
  • @DanielDavila:在您的 .mm 文件中添加 #include <Foundation/Foundation.h>
【解决方案2】:

如果您的代码从主应用程序包运行,那么您可以使用以下内容:

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

const char *cCursorImagePath = [cursorImagePath fileSystemRepresentation];

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

(注意:将要在其中使用 Objective-C 的任何文件的文件扩展名从 .cpp 更改为 .mm)。

NSBundle(或CFBundle)可用于定位应用程序包内资源的(完整)路径。见Bundle Programming Guide: Getting the Path to a Resource

另外,我不确定您的应用程序有多“可可”。具体来说,我不确定您是否已经拥有NSAutoreleasePool。在 Console.app 或 Xcode 的调试控制台中观察输出,以获取与 __NSAutoreleaseNoPool() - just leaking 一致的错误消息。如果您确实看到了这些,则需要在上面的代码中加上以下内容:

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

关于“我是否必须包含一些内容才能使用此代码?这是一个 c++ 应用程序”:

是的,您需要导入(如果您还没有这样做,还需要链接):

#import <Foundation/Foundation.h>

#import 是 Objective-C 的智能 #include:它确保它只包含一次)。

您说您的应用程序是 C++,但 2 个主要的 GUI 框架是 Carbon(基于 C 的 HIToolbox)或 Cocoa(基于 Objective-C)。您知道您使用的是哪一个,或者您正在使用隐藏这些细节的另一个框架(看起来像 SDL)吗?

【讨论】:

  • 我是否必须包含一些内容才能使用此代码?这是一个 C++ 应用程序
  • 我不明白你上次的编辑,当我创建项目时,它是一个基于可可的应用程序,但我删除了 appdelegate.h 、 .m 和 main.m 以放置我的 c++ 代码和使用 SDL
【解决方案3】:

你的意思是"./Resources/cursor.png"

"/Resources/cursor.png" 在根文件系统中

"./Resources/cursor.png" 是相对于工作目录的。

或者您可以相对于用户的主路径进行操作

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

这不适用于不填充环境变量的基于 Unix 的操作系统。我被告知 OS X 没有。不管它为什么失败,你都可以在那时使用getpwuid()

编辑:

为了完整性而添加。您可以使用找到的代码here 将其基于可执行文件的路径。实际上,几乎我所有的 Unix 代码都基于主目录并回退到 /etc 中的文件。这就是我的代码的大多数用户想要的(作为我想要的用户)。

【讨论】:

  • 我在 Windows 上运行了相同的代码,它是“/Resources/cursor.png”,我尝试添加 .之前 / 但它有同样的问题:(
  • @DanielDavila 我猜您使用的是 unix 变体,因为您的斜杠是正向 (/)。代码现在应该在什么操作系统上运行?您是从 IDE 运行它吗?如果是这样,您的工作目录可能不在您认为的位置。这通常是 Windows 版本的问题。尝试从您希望它与“./”相关的目录运行
  • 我使用的是 OSX,您发布的代码不起作用。 IDE 是 Xcode。该应用程序是一个简单的游戏,它应该是多平台的。
  • 在我的领土之外。对OSX一无所知。我会从 NSHomeDirectory() 的 google 开始,看看它会带给你什么。 我只想提一下再次从它所在的文件夹运行 exe。您的 IDE 很有可能从项目或解决方案的目录中运行它
  • @JoeMcGrath:Mac 中没有 exe。 mac中的“program”等价物是一种目录,但不能更改工作目录的内容(“program”目录内的子目录)
猜你喜欢
  • 2016-08-30
  • 2012-03-02
  • 2013-12-20
  • 1970-01-01
  • 2011-01-24
  • 2013-10-25
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多