5

From what I understand, a std::stringstream is represented internally not as an std::string but rather as a set of std::string instances. (correct me if I am wrong).

I have data represented as an std::stringstream and I want to pass it to a C function (clCreateProgramWithSource from OpenCL) that expects the data as an array of arrays of chars. (const char**).

Is there some way to do this without first creating a single string that holds the entire content of the stringstream, for example in the following way:

std::string tmp1 = my_stringstream.str();
const char* tmp2 = tmp1.c_str();
const char** tmp3 = &tmp2;

EDIT

Follow-up question:

If this is not possible, is there some alternative to std::stringstream, inheriting from std::ostream, that allows this low level access?

Joel
  • 1,295
  • 15
  • 30
  • 1
    The implementation of `stringstream` is not specified. For C++, the internal `streambuf` object would be a useful low-level point of access, but for C interop your code is basically as good as it can be. – Kerrek SB Jan 19 '13 at 11:57
  • @KerrekSB OK, I was thinking that there should be some way around it, that would at least work for a standard `stringstream` implementation. With fallback to the above code in other cases. – Joel Jan 19 '13 at 12:07
  • 2
    As fallback, you can derive from `ostream` or `streambuf` to implement your own stream, if concatenating and splitting stream _is actually a bottleneck_. (http://stackoverflow.com/questions/6490499/how-can-i-derive-my-own-stream-from-a-standard-stream) – Lol4t0 Jan 19 '13 at 12:59
  • 5
    You are are trying to optimize at the entirely wrong level. Copying a string costs *literally* nothing compared to what `clCreateProgramWithSource` does. It's like removing a fly from an elephant and hope it will lose weight. – Bo Persson Jan 19 '13 at 13:13
  • @Lol4t0 Thanks for the pointer on how to implement a stream. I will consider it, *if it actually turns out to be a bottle neck* as you rightly point out. – Joel Jan 19 '13 at 13:42
  • 1
    @BoPersson I am 100 % sure you are right that the overhead in `clCreateProgramWithSource`. In fact, I've tested building up LLVM intermediate code directly instead of code generation and compilation with Clang, only to realize that there was virtually no difference in performance. And my OpenCL implementation uses Clang/LLVM afaik. But I'm still interested in the `std::stringstream` to `char**` conversion for C++/C interop in general. – Joel Jan 19 '13 at 13:50
  • 2
    I'm not sure how correct it is, but I did this: `stream.str().c_str()` – Tomáš Zato Mar 18 '13 at 03:02

1 Answers1

1

By getting the streambuf of the stringstream we can explicitly set the buffer it should use:

#include <sstream>

constexpr size_t buffer_size = 512;

void dummy_clCreateProgramWithSource(const char **strings) {}

int main () {
  char * ss_buffer = new char[buffer_size];
  std::stringstream filestr; // TODO initialize from file
  filestr.rdbuf()->pubsetbuf(ss_buffer,buffer_size);
  const char** extra_indirection = const_cast<const char **>(&ss_buffer);
  dummy_clCreateProgramWithSource(extra_indirection);
  return 0;
}

Note the const_cast that tells what may be a lie; we are promising OpenCL that we won't write to the stringstream after calling clCreateProgramWithSource.

TamaMcGlinn
  • 2,840
  • 23
  • 34