2

I'm trying to use SWIG to create a Go wrapper for a C++ API that uses std::istream to read binary data. I'd like to be able to pass an io.Reader to these APIs, but I'm not sure how to create a mapping between it and std::istream. I know I need to implement a std::streambuf subclass and I assume the rest will involve directors and typemaps, but I'm not familiar enough with SWIG to figure out the right combination.

Any ideas?

David Brown
  • 35,411
  • 11
  • 83
  • 132

1 Answers1

-1

io.Reader is too general to be passed to C functions -- it might not be backed on a real file at all (it's just a class that implements a Read(...) function)

What you could do (so long as you aren't on windows) is use os.Pipe() to give you a ture FH object, but sadly the stock std::*stream doesn't have any way of creating a stream from an open file handle.

The pipe bit looks something like this:

func wrapReader(r io.Reader) uintptr {
    pr, pw, err := os.Pipe()
    if err != nil {
        panic(err)
    }

    go func () {
        _, _ io.Copy(pw, r)
        _ = pw.Close()
    }()

    return pr
}

If you combine that some of the code in this answer How to construct a c++ fstream from a POSIX file descriptor? you might get what you need

Community
  • 1
  • 1
Ash Berlin-Taylor
  • 3,879
  • 29
  • 34
  • 1
    `std::istream` is just an abstraction over a stream of bytes like `io.Reader`. Only the `std::ifstream` implementation actually deals with files. – David Brown May 22 '16 at 20:33
  • True,true. It's more work but probably possible then to write an adapter that calls back into go to read from the io.Reader. Getting the GC right so that the reader doesn't get destroyed under you is where most of the work might be then. – Ash Berlin-Taylor May 22 '16 at 22:39
  • 1
    Well, since Go doesn't allow Go pointers to be passed to C code, the usual solution is to store the object in a map and pass the key back and forth. The object won't be GC'd until it's remove from the map. My question isn't so much about how to make the `std::streambuf`, but instead how to get SWIG to use that implementation whenever it encounters a C++ API that takes a `std::istream`. – David Brown May 23 '16 at 14:51