C++ 从std::istream读取SDL_rOps

C++ 从std::istream读取SDL_rOps,c++,sdl,istream,C++,Sdl,Istream,我很惊讶谷歌没有找到解决方案。我正在寻找一种解决方案,允许SDL_RWops与std::istream一起使用。SDL_RWops是在SDL中读取/写入数据的替代机制 有解决这个问题的网站的链接吗 一个显而易见的解决方案是将足够的数据预读入内存,然后使用SDL_RWFromMem。但是,这样做的缺点是我需要事先知道文件大小 似乎这个问题可以通过“覆盖”SDL_rOps函数来解决…我很抱歉回答我自己的问题,但这让我有一段时间都很紧张,这就是我提出的解决方案: int istream_seek( s

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

有解决这个问题的网站的链接吗

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


似乎这个问题可以通过“覆盖”SDL_rOps函数来解决…

我很抱歉回答我自己的问题,但这让我有一段时间都很紧张,这就是我提出的解决方案:

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传递给转换函数:/


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

如果您试图从istream获取SDL\u RWops结构,可以通过将整个istream读入内存,然后使用SDL\u rFromMem获取一个结构来表示它

下面是一个简单的例子;请注意,这是不安全的,因为没有进行健康检查。例如,如果文件大小为0,则访问缓冲区[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
//打开位图
std::ifstream位图(“bitmap.bmp”);
//查找位图文件的大小
bitmap.seekg(0,std::ios\u base::end);
std::istream::pos_tye fileSize=bitmap.tellg();
位图。seekg(0);
//分配一个缓冲区来存储文件
向量缓冲区(文件大小);
//将istream复制到缓冲区中
std::copy(std::istreambuf_迭代器(位图),std::istreambuf_迭代器(),buffer.begin());
//获取文件的SDL_RWops结构
SDL_RWops*rw=SDL_rwfrommmem(&buffer[0],buffer.size());
//使用SDL_RWops结构进行操作

你的意思是你想从一个istream创建一个RWops结构?那不是一个成功的例子,我不明白你想做什么。我试图从istream读取SDL数据(就像SDL_图像中的图像),我已经写过我不能这样做,因为我不想将整个文件预加载到内存中。如果我想从文件中读取,我会使用IMG_Load:)。我想从通过istream访问的自定义容器加载。您只提到这是一个问题,因为“您事先不知道文件的大小”是的,这可以用于任何istream,我只是使用了一个istream作为示例,因为这是制作istream的最简单方法。叹气。。。想象一下--我从一个文件归档库中得到一个istream。没有尺寸,只是一个istream。此外,在该zipfile中,存储了多个文件。预加载文件将加载1GB的图像。使用rwops->type,您可以允许istream、ostream或iostream。使用NULL作为写入函数似乎很可怕。最好创建一个使用SDL_SetError并返回-1的函数。@Caspin,谢谢,非常有用的提示!尽管如此,发布的代码仍然不起作用。。。。我正在尝试调试它,但没有任何线索:/好的,我的错,我没有将ios::binary传递给测试用例:)