我正在编写一些多平台C++代码。因此,需要使用fopen、fgetpos等。以下内容在iOS上运行较早,随着我更新到最新版本,它停止了工作。
我在Shaders文件夹中有几个文本文件Shader.vsh和Shader.fsh,它们正在被复制到捆绑包中。为了打开文件,我执行以下操作。。
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFStringRef cfstrFilename = CFSTRFromConstCharPtr( "Shader" );
CFStringRef cfstrFileType = CFSTRFromConstCharPtr( "vsh" );
CFStringRef cfstrSubDir = CFSTRFromConstCharPtr( "Shaders" );
CFURLRef resourcesURL = CFBundleCopyResourceURL( mainBundle, cfstrFilename, cfstrFileType, cfstrSubDir );
CFStringRef str = CFURLCopyFileSystemPath( resourcesURL, kCFURLPOSIXPathStyle );
CFRelease( resourcesURL );
char path[ PATH_MAX ];
CFStringGetCString( str, path, FILENAME_MAX, kCFStringEncodingASCII );
CFRelease( str );
FILE* fp = fopen( path, "rb" );
此时,fp为非NULL。所以我认为它成功了。后来,当我尝试做时
fpos_t pos;
int result = fgetpos( fp, &fpos_t );
result=-1,errno=0x2,我认为这是找不到的文件。
正如我前面提到的,这曾经在某个时候对以前的版本起作用。我再次开始处理这个问题,并在这个过程中更新到最新的XCode等,事情停止了工作。
我传递到fopen的文件的路径原来是/Users/shammi/Library/Application-Support/iPhone Simulator/6.1/Applications/9132490F-71AC-4C61-A584-E8F6C5B261FF/TestApp.app/Shaders/Shader.vsh我可以在finder/console中查看并打开该文件,并确认其有效。
我做错了什么?有没有其他选择可以让我使用便携式IO功能?
发现问题。我在这里没有提到的是上面两段代码之间发生的事情。在此之前,我曾经有自己的引用计数解决方案,最近我改为使用shared_ptr。我自己的引用计数解决方案允许隐式强制转换。使用shared_ptr,您无法做到这一点。这是确切的代码。。。
std::shared_ptr<BinaryStream>BundleNamespace::OpenStream(const char*_szPath,
BinaryStream::Mode _eMode )
{
std::shared_ptr< BinaryStream > pStream = __super::OpenStream( _szPath, _eMode );
if ( !pStream )
{
std::string strDir;
std::string strFile;
std::string strExt;
SplitPath( _szPath, strDir, strFile, strExt );
std::string strFullPath = GetResourcePathFor( strFile.c_str(), strExt.c_str(), strDir.c_str() );
FILE* fp = fopen( strFullPath.c_str(), _eMode == BinaryStream::Mode_Read ? "r" : "w+b" );
pStream = std::make_shared<FileStream>( fp, _eMode );
}
return pStream;
}
这里的问题是
pStream = std::make_shared<FileStream>( fp, _eMode );
我的FileStream的析构函数调用fclose(m_pFile)。这里的解决方案是将其更改为.
pStream = std::static_pointer_cast< BinaryStream >( std::make_shared<FileStream>( fp, _eMode ) );`
此外,与试图解密errno相比,使用perror()更有用。