5

我很惊讶谷歌没有找到解决方案。我正在寻找一种允许 SDL_RWops 与 std::istream 一起使用的解决方案。SDL_RWops 是在 SDL 中读取/写入数据的替代机制。

任何指向解决问题的网站的链接?

一个明显的解决方案是将足够的数据预读到内存中,然后使用 SDL_RWFromMem。但是,这样做的缺点是我需要事先知道文件大小。

似乎问题可以通过“覆盖” SDL_RWops 函数以某种方式解决......

4

2 回答 2

6

我很难回答自己的问题,但它让我心烦意乱了一段时间,这就是我想出的解决方案:

int istream_seek( struct SDL_RWops *context, int offset, int whence)
{
    std::istream* stream = (std::istream*) context->hidden.unknown.data1;

         if ( whence == SEEK_SET )
        stream->seekg ( offset, std::ios::beg );
    else if ( whence == SEEK_CUR )
        stream->seekg ( offset, std::ios::cur );
    else if ( whence == SEEK_END )
         stream->seekg ( offset, std::ios::end );

    return stream->fail() ? -1 : stream->tellg();
}


int istream_read(SDL_RWops *context, void *ptr, int size, int maxnum)
{
    if ( size == 0 ) return -1;
    std::istream* stream = (std::istream*) context->hidden.unknown.data1;
    stream->read( (char*)ptr, size * maxnum );

    return stream->bad() ? -1 : stream->gcount() / size;
}

int istream_close( SDL_RWops *context )
{
    if ( context ) {
        SDL_FreeRW( context );
    }
    return 0;
}


SDL_RWops *SDL_RWFromIStream( std::istream& stream )
{
    SDL_RWops *rwops;
    rwops = SDL_AllocRW();

    if ( rwops != NULL ) 
    {
        rwops->seek = istream_seek;
        rwops->read = istream_read;
        rwops->write = NULL;
        rwops->close = istream_close;
        rwops->hidden.unknown.data1 = &stream;
    }
    return rwops;
}

在 istream 永远不会被 SDL 释放(并且它们通过操作存在)的假设下工作。也只有 istream 支持,将为 ostream 完成一个单独的函数——我知道我可以传递 iostream,但这不允许将 istream 传递给转换函数:/。

欢迎任何有关错误或升级的提示。

于 2010-01-13T16:57:19.807 回答
1

如果您尝试从 istream 获取 SDL_RWops 结构,您可以通过将整个 istream 读入内存然后使用 SDL_RWFromMem 获取一个结构来表示它。

以下是一个简单的例子;请注意,这是不安全的,因为没有进行完整性检查。例如,如果文件的大小为 0,则访问 buffer[0] 可能会引发异常或在调试版本中断言。

// Open a bitmap
std::ifstream bitmap("bitmap.bmp");

// Find the bitmap file's size
bitmap.seekg(0, std::ios_base::end);
std::istream::pos_tye fileSize = bitmap.tellg();
bitmap.seekg(0);

// Allocate a buffer to store the file in
std::vector<unsigned char> buffer(fileSize);

// Copy the istream into the buffer
std::copy(std::istreambuf_iterator<unsigned char>(bitmap), std::istreambuf_iterator<unsigned char>(), buffer.begin());

// Get an SDL_RWops struct for the file
SDL_RWops* rw = SDL_RWFromMem(&buffer[0], buffer.size());

// Do stuff with the SDL_RWops struct
于 2010-01-13T16:58:20.813 回答