C ++:无法读取macos包中的资源文件

时间:2018-05-07 12:39:55

标签: macos opengl core-foundation

背景

我正在写一个" Hello Rectangle" OpenGL应用程序。我希望它是一个独立的.app,而不仅仅是一个" UNIX可执行文件。"代码从Terminal.app运行良好。

我没有使用Xcode;我在磁盘空间上非常非常,我没有做iOS开发。 相反,我使用了酿造工具链,包括gcc-8glfwglew

我根据此SO question构建了我的发布目录,如下所示:

Contents
├── Frameworks
│   ├── libGLEW.2.1.dylib
│   ├── libgcc_s.1.dylib
│   ├── libglfw.3.dylib
│   └── libstdc++.6.dylib
├── MacOS
│   ├── hello-rect    <- the actual binary
│   └── launcher.sh   <- entry wrapper for working dir as the above link suggests
├── Resources
│   ├── rect.frag
│   └── rect.vert
└── Info.plist

我还修改了二进制对dylibs的引用。但它不会运行。

经过几个小时的Google搜索后,这个SO answer以及此SO question和其他几个人确信我应该使用CoreFoundation来读取Resources中的这两个着色器文件(文本文件) 1}}。

问题:

我尝试了以下代码(通过上面的链接粘贴稍作修改),但它会出现段错误:

const char* textFileReadCF(const char *&filename){
  // Get a reference to the main bundle
  CFBundleRef mainBundle = CFBundleGetMainBundle();

  // Get a reference to the file's URL
  CFStringRef filenameHandle = CFStringRef(filename);

  // ------ segfault 11 here ------
  CFURLRef fileURL = CFBundleCopyResourceURL(mainBundle, filenameHandle, NULL, NULL);

  // Convert the URL reference into a string reference
  CFStringRef filePath = CFURLCopyFileSystemPath(fileURL, kCFURLPOSIXPathStyle);

  // Get the system encoding method
  CFStringEncoding encodingMethod = CFStringGetSystemEncoding();

  // Convert the string reference into a C string
  const char *path = CFStringGetCStringPtr(filePath, encodingMethod);

  // the real read function, read in file and returns all as a big char* arr
  return textFileRead(path);
}

// this runs fine before packing and I didn't change, 
// just for the sake of completeness
const char *textFileRead(const char *filename){
  std::ifstream shaderFile(filename);
  std::ostringstream shaderBuffer;
  shaderBuffer << shaderFile.rdbuf();
  std::string shaderBufferStr = shaderBuffer.str();
  // Warning: safe only until shaderBufferStr is destroyed or modified
  char * ret = new char[shaderBufferStr.size()];
  std::strcpy(ret, shaderBufferStr.c_str());
  return ret;
}

textFileReadCF将使用"rect.vert""rect.vert"(不是文字,但const char*持有)来调用两次。

我不知道为什么会出现段错误。我确定有一个mainBundleassert(已省略),filenameHandle有效,但我不知道在哪里看。

1 个答案:

答案 0 :(得分:0)

原来我需要CoreFoundation。我只需要GLFW

在早期版本中,我的发布目录看起来像这样:

Contents
├── Frameworks
│   ├── libGLEW.2.1.dylib
│   ├── libgcc_s.1.dylib
│   ├── libglfw.3.dylib
│   └── libstdc++.6.dylib
├── MacOS
│   ├── hello-rect    <- the actual binary
│   ├── launcher.sh   <- entry wrapper for working dir as the above link suggests
│   ├── rect.frag
│   └── rect.vert
└── Info.plist

因为非捆绑版本显然无处可寻cwd。 我甚至不知道有Resources。那时我的代码也没有运行;我的Google跟踪让我相信CoreFoundation是解决方案。只有在我检查了有关CoreFoundation的文档之后,才知道应该Resources。当所有的点都连接起来时,我偶然遇到了这个SO question

显然我的GLFW版本的行为与链接状态相似:(直接来自源代码)

  

//更改为我们的应用程序包的资源目录(如果存在)

所以只需将捆绑包用在盒子外面,只需构建相关的版本目录,然后直接使用textFileRead"rect.vert"调用"rect.vert",我们&# 39;重新设定。