patterncppMinor
C++ demo code for interaction with C
Viewed 0 times
withinteractionforcodedemo
Problem
I want to show how to interact with C from C++ and chose a simple and small library to demonstrate. zlib's
Does anyone see anything fundamentally wrong with my presentaion? The main code I present here is in
Intro section:
Core class
Helper functions
```
vector read(const string& infn) {
ifstream inf{ infn, ifstream::binary };
if(!inf) throw std::runtime_error("open error");
inf.seekg(0, inf.end); // go to end of file
const auto laenge = inf.tellg(); // current pos is file size
if(laenge > 102410241024) throw std::runtime_error(" data(laenge); // make room
inf.read(data.data(), laenge); // read all at once
return std::move(data); // make doubly sure data is not copied
}
void pack(const string& infn, const string& outfn) {
vector indata = read(infn); // read input
GzWrite gz{outfn}; // init output
auto res = gz.write(indata.data(), indata.size());
if(res==0)
gzopen, gzwrite and gzclose looked like a reasonably closed set of funtions.Does anyone see anything fundamentally wrong with my presentaion? The main code I present here is in
class GzWrite.Intro section:
#include
#include
#include // ifstream
#include // runtime_error
#include // cerr
// C-Headers:
#include // gzXyz; sudo aptitude install libz-dev
#include // strerror
#include // errno
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
using std::ifstream; using std::ofstream; using std::string; using std::vector;
namespace {
constexpr size_t BLOCK_SZ = 256*1024;
constexpr int LEVEL = Z_DEFAULT_COMPRESSION;Core class
struct GzWrite { // RAII-Wrapper
gzFile gz_ ; // C-Struct aus zlib.h
explicit GzWrite(const string& filename)
: gz_{gzopen(filename.c_str(),"wb9")} // 'w': write, 'b':binary, '9':level
{
if(gz_==NULL) throw std::runtime_error(strerror(errno));
}
~GzWrite() {
gzclose(gz_);
}
int write(const char* data, size_t len) {
return gzwrite(gz_, data, len);
}
GzWrite(const GzWrite&) = delete; // no copy
GzWrite& operator=(const GzWrite&) = delete; // no assign
};Helper functions
```
vector read(const string& infn) {
ifstream inf{ infn, ifstream::binary };
if(!inf) throw std::runtime_error("open error");
inf.seekg(0, inf.end); // go to end of file
const auto laenge = inf.tellg(); // current pos is file size
if(laenge > 102410241024) throw std::runtime_error(" data(laenge); // make room
inf.read(data.data(), laenge); // read all at once
return std::move(data); // make doubly sure data is not copied
}
void pack(const string& infn, const string& outfn) {
vector indata = read(infn); // read input
GzWrite gz{outfn}; // init output
auto res = gz.write(indata.data(), indata.size());
if(res==0)
Solution
This example is mostly about making and using a RAII wrapper, not about calling C from C++ (which is trivial).
If you want to show how to call C-like interfaces, then use zlib directly, without wrapping it.
If you want to show the native C++ way to wrap a C interface, then the wrapper should be an
Some confusing names:
If you want to show how to call C-like interfaces, then use zlib directly, without wrapping it.
If you want to show the native C++ way to wrap a C interface, then the wrapper should be an
iostream subclass, like gzstream.pack should read blocks of finite size rather than reading the whole file at once. It's a compression utility, so it's likely to be used on files that won't fit in memory!Some confusing names:
GzWriteinstances aren't writes; they're streams. How aboutGzStreamor (if it uses the iostreams interface)gzostream?
- Don't call a function
read; it's easy to confuse with Posixread. This is traditionally calledslurporread_file.
infnwill probably be interpreted as "in-function", not "in-filename". How aboutinfile?
laenge(Länge?):length
BLOCK_SZ and LEVEL are unused.Context
StackExchange Code Review Q#51292, answer score: 6
Revisions (0)
No revisions yet.