C# 继承std :: istream或等效

更新时间:2024-04-26 下载TXT文档 下载Word文档

我需要在流上桥接两个库。

QDataStream which is a stream from Qt

和其他库中的某些功能,如下所示:

void read_something(istream& i);

我无法控制QDataStream的创建方式,并且不允许更改read_somthing函数的接口。

我首先想到的是编写一个继承istream并包装QDataStream的类。有人做过吗?

如果我认为这不是正确的方法,那么我想知道实现此目标的最佳方法是什么。 短码网-DuanMa.NET

  • 您是在编写自己的read_something实现,还是在尝试调用此函数?

您应该做的是编写一个使用QDataStream readBytes和writeBytes实现其功能的streambuf。然后使用rdbuf将streambuf注册到istream中(您也可以编写一个istream后代,在初始化时执行此操作)。

Boost包含一个旨在促进streambuf编写的库。使用它可能比理解streambuf界面更简单(个人而言,我从未使用过它,但是我编写了多个streambuf;我将看看是否有可以发布的示例)。

编辑:以下内容(法语注释-来自fr.comp.lang.c的法语常见问题解答-,我没有时间进行翻译,我认为离开它们比删除它们更好)将FILE *调用包装到streambuf中。这也是使用私有继承的示例:确保可能是成员的成员在基类之前被初始化。对于IOStream,基类也可以接收NULL指针,然后使用成员init()来设置streambuf。

#include <stdio.h>
#include 

#include <iostream>
#include <streambuf>

// streambuf minimal encapsulant un FILE*
//    - utilise les tampons de FILE donc n'a pas de tampon interne en
//      sortie et a un tampon interne de taille 1 en entree car l'interface
//      de streambuf ne permet pas de faire moins;
//    - ne permet pas la mise en place d'un tampon
//    - une version plus complete devrait permettre d'acceder aux
//      informations d'erreur plus precises de FILE* et interfacer aussi
//      les autres possibilites de FILE* (entre autres synchroniser les
//      sungetc/sputbackc avec la possibilite correspondante de FILE*)

class FILEbuf: public std::streambuf
{
public:

  explicit FILEbuf(FILE* cstream);
  // cstream doit etre non NULL.

protected:

  std::streambuf* setbuf(char_type* s, std::streamsize n);

  int_type overflow(int_type c);
  int      sync();

  int_type underflow();

private:

  FILE*    cstream_;
  char     inputBuffer_[1];
};

FILEbuf::FILEbuf(FILE* cstream)
  : cstream_(cstream)
{
  // le constructeur de streambuf equivaut a
  // setp(NULL, NULL);
  // setg(NULL, NULL, NULL);
  assert(cstream != NULL);
}

std::streambuf* FILEbuf::setbuf(char_type* s, std::streamsize n)
{
  // ne fait rien, ce qui est autorise.  Une version plus complete
  // devrait vraissemblablement utiliser setvbuf
  return NULL;
}

FILEbuf::int_type FILEbuf::overflow(int_type c)
{
  if (traits_type::eq_int_type(c, traits_type::eof())) {
    // la norme ne le demande pas exactement, mais si on nous passe eof
    // la coutume est de faire la meme chose que sync()
    return (sync() == 0
        ? traits_type::not_eof(c)
        : traits_type::eof());
  } else {
    return ((fputc(c, cstream_) != EOF)
        ? traits_type::not_eof(c)
        : traits_type::eof());
  }
}

int FILEbuf::sync()
{
  return (fflush(cstream_) == 0
      ? 0
      : -1);
}

FILEbuf::int_type FILEbuf::underflow()
{
  // Assurance contre des implementations pas strictement conformes a la
  // norme qui guaranti que le test est vrai.  Cette guarantie n'existait
  // pas dans les IOStream classiques.
  if (gptr() == NULL || gptr() >= egptr()) {
    int gotted = fgetc(cstream_);
    if (gotted == EOF) {
      return traits_type::eof();
    } else {
      *inputBuffer_ = gotted;
      setg(inputBuffer_, inputBuffer_, inputBuffer_+1);
      return traits_type::to_int_type(*inputBuffer_);
    }
  } else {
    return traits_type::to_int_type(*inputBuffer_);
  }
}

// ostream minimal facilitant l'utilisation d'un FILEbuf
// herite de maniere privee de FILEbuf, ce qui permet de s'assurer
// qu'il est bien initialise avant std::ostream

class oFILEstream: private FILEbuf, public std::ostream 
{
public:
  explicit oFILEstream(FILE* cstream);
};

oFILEstream::oFILEstream(FILE* cstream)
  : FILEbuf(cstream), std::ostream(this)
{
}

// istream minimal facilitant l'utilisation d'un FILEbuf
// herite de maniere privee de FILEbuf, ce qui permet de s'assurer
// qu'il est bien initialise avant std::istream

class iFILEstream: private FILEbuf, public std::istream
{
public:
  explicit iFILEstream(FILE* cstream);
};

iFILEstream::iFILEstream(FILE* cstream)
  : FILEbuf(cstream), std::istream(this)
{
}

// petit programme de test
#include 
int main(int argc, char* argv[])
{
  FILE* ocstream = fopen("result","w");
  assert (ocstream != NULL);
  oFILEstream ocppstream(ocstream);
  ocppstream <<"Du texte";
  fprintf(ocstream," melange");
  fclose(ocstream);
  FILE* icstream = fopen("result","r");
  assert (icstream != NULL);
  iFILEstream icppstream(icstream);
  std::string word1;
  std::string word2;
  icppstream >> word1;
  icppstream >> word2;
  char buf[1024];
  fgets(buf, 1024, icstream);
  std::cout <<"Got :" << word1 << ':' << word2 << ':' << buf << '\
';
}
  • 注意,更简单的替代方法是使用接收器和源概念。例如,接收器对象将包装FILE *,并且仅需要实现一个写函数,在该函数中将调用以对FILE指针进行fwrite。然后可以将接收器包装在boost :: iostream :: stream <Sink>中,然后可以将其视为std :: ostream。啊,我看到有人已经在下面指出了这种解决方案。

增强流解决方案:

namespace boost {
    namespace iostreams {

        class DataStreamSource
        {
        public:
            typedef char char_type;
            typedef source_tag  category;

            DataStreamSource( QDataStream *const source ) : m_source(source){
            }
            std::streamsize read(char* buffer, std::streamsize n) {
                return m_source ? m_source->readRawData(buffer, n) : -1;
            }

        private:
            QDataStream *const m_source;
        };
    }
}

// using DataStreamSource 
namespace io = boost::iostreams;
QFile fl("temp.bin");
fl.open(QIODevice::ReadOnly);
QDataStream s(&fl);
io::stream< io::DataStreamSource > dataStream( &s );   
read_something(dataStream);
  • @lyxera Ive还制作了一个接收器-源-设备QIODevice桥:stackoverflow.com/questions/848269/mixing-qt-with-stl-and-bo ost-are-are-br-bridges-make-it- EAS y / 856812#856812

以上就是短码网小编为大家整理的《C# 继承std :: istream或等效》相关内容,希望大家喜欢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若内容造成侵权/违法违规/事实不符,请将联系本站反馈,一经查实,立即处理!

C# 继承std :: istream或等效》文档下载仅供参考学习,下载后请在24小时内删除。

转载注明出处:https://www.duanma.net/article/c847a871217.html

回到顶部