macos - C++:无法读取 macOS 包中的资源文件
问题描述
背景:
我正在编写一个“Hello Rectangle”OpenGL 应用程序。我希望它是独立.app
的,而不仅仅是“UNIX 可执行文件”。代码从 Terminal.app 运行良好。
我没有使用 Xcode;我的磁盘空间非常紧张,而且我没有做 iOS 开发。相反,我使用的是 brewed 工具链,包括gcc-8
,glfw
和glew
.
我根据这个SO 问题构建了我的发布目录,如下所示:
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 的引用。但它不会运行。
经过几个小时的谷歌搜索,这个SO 答案和这个SO问题以及其他几个问题让我确信我应该使用.CoreFoundation
Resources
问题:
我尝试了以下代码(从上面的链接粘贴并稍作修改),但它得到了段错误:
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"
and调用两次"rect.vert"
(不是字面意思,而是const char*
持有它们)。
我不知道为什么会出现段错误。我确保有一个mainBundle
通过assert
(省略),据我所知这filenameHandle
是有效的,但除此之外我不知道去哪里找。
解决方案
原来我不需要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
。当时我的代码也没有运行;我的谷歌跟踪让我相信这CoreFoundation
是解决方案。直到我检查了文档,CoreFoundation
我才知道应该有Resources
. 当所有的点都连接在一起时,我只是偶然遇到了这个SO question 。
显然我的版本GLFW
也表现得像链接状态:(直接来自源)
// 切换到我们的应用程序包的资源目录,如果存在的话
因此,使捆绑包开箱即用所需要做的就是,像讨论的那样构造发布目录,然后直接textFileRead
使用"rect.vert"
and调用"rect.vert"
,我们都准备好了。
推荐阅读
- xunit - 如何使用 MassTransit 测试工具通过构造函数依赖注入测试消费者?
- tfs - 在 TFS 2018 中自动触发构建
- angular - 从订阅中获取数据并分配给局部变量
- php - 从数据库中选择图像并显示在网页上(PHP)
- python - 与 PySide2 QWebEngineView 中嵌入的 Folium Map 交互
- entity-framework - Add-Migration 在 VS2017 和 VS2015 中生成不同的迁移
- node.js - 使用对象作为在 router.get 中查找值的键
- javascript - 如果任何输入或选择的表单为空,如何删除表格行?
- android - 折叠工具栏标题动画速度
- laravel-5 - 雄辩的查询以获得数据库中的最高值和第二高值