Reputation: 2826
I am fairly new to C++ and wanted to convert a *FILE (such as returned by popen()) to a iostream to be used with functions such as getline etc. I found the following code http://fw-geekycoder.blogspot.co.za/2011/06/how-to-convert-c-file-to-c-iostream.html, as well as similar code from a bunch of places, but the compiler moans about boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);
and boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);
#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
void write() {
FILE* fp = fopen("whatever.txt", "w");
if (fp == NULL) {
perror("fopen error");
}
int fd = fileno(fp);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);
std::ostream os(&bis);
os << "Hello World!" << std::endl;
fclose(fp);
}
void read() {
FILE* fp = fopen("whatever.txt", "r");
if (fp == NULL) {
perror("fopen error");
}
int fd = fileno(fp);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> bis(fd);
std::istream is(&bis);
while (is) {
std::string line;
std::getline(is, line);
std::cout << line << std::endl;
}
fclose(fp);
}
int main() {
write();
read();
return 0;
}
It seems like my system finds boost, but as if the API or something changed. What is the problem, here is my output from eclipse:
make all
Building file: ../src/boostPopenHandler.cpp
Invoking: GCC C++ Compiler
g++ -D__GXX_EXPERIMENTAL_CXX0X__ -I../../emdw/src -I../../patrecII/src -I../../ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"src/boostPopenHandler.d" -MT"src/boostPopenHandler.d" -o"src/boostPopenHandler.o" "../src/boostPopenHandler.cpp"
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = char; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:13:83: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
{ open(detail::path(path), mode); }
^
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:52:5: error: initializing argument 1 of ‘boost::iostreams::detail::path::path(const char*)’ [-fpermissive]
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = char; T = boost::iostreams::file_descriptor_source; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::input_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:26:85: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:194:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
{ open(detail::path(path), mode); }
^
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:52:5: error: initializing argument 1 of ‘boost::iostreams::detail::path::path(const char*)’ [-fpermissive]
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
make: *** [src/boostPopenHandler.o] Error 1
Edit:
Following the answer from Selçuk Cihan, I changed the relevant code to:
boost::iostreams::file_descriptor_source fds(fd);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink>
...
boost::iostreams::file_descriptor_source fds(fd);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source>
But I still get a list of compile errors:
**** Build of configuration Debug for project boostPopenHandler ****
make all
Building file: ../src/boostPopenHandler.cpp
Invoking: GCC C++ Compiler
g++ -I../../emdw/src -I../../patrecII/src -I../../ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"src/boostPopenHandler.d" -MT"src/boostPopenHandler.d" -o"src/boostPopenHandler.o" "../src/boostPopenHandler.cpp"
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = int; std::ios_base::openmode = std::_Ios_Openmode]’:
../src/boostPopenHandler.cpp:13:52: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:194:36: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
{ open(detail::path(path), mode); }
^
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:52:5: error: initializing argument 1 of ‘boost::iostreams::detail::path::path(const char*)’ [-fpermissive]
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: error: no matching function for call to ‘boost::iostreams::detail::path::path(const boost::iostreams::file_descriptor_source&)’
{ open(detail::path(path), mode); }
^
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: note: candidates are:
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:138:5: note: boost::iostreams::detail::path::path(const wstring&)
path(const std::wstring&);
^
/usr/include/boost/iostreams/detail/path.hpp:138:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const wstring& {aka const std::basic_string<wchar_t>&}’
/usr/include/boost/iostreams/detail/path.hpp:70:5: note: boost::iostreams::detail::path::path(const boost::iostreams::detail::path&)
path(const path& p)
^
/usr/include/boost/iostreams/detail/path.hpp:70:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const boost::iostreams::detail::path&’
/usr/include/boost/iostreams/detail/path.hpp:64:14: note: template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::codecvt_type*)
explicit path(const Path& p, typename Path::codecvt_type* = 0)
^
/usr/include/boost/iostreams/detail/path.hpp:64:14: note: template argument deduction/substitution failed:
/usr/include/boost/iostreams/detail/path.hpp: In substitution of ‘template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::codecvt_type*) [with Path = boost::iostreams::file_descriptor_source]’:
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: required from ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:64:14: error: no type named ‘codecvt_type’ in ‘class boost::iostreams::file_descriptor_source’
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:57:14: note: template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::external_string_type*)
explicit path(const Path& p, typename Path::external_string_type* = 0)
^
/usr/include/boost/iostreams/detail/path.hpp:57:14: note: template argument deduction/substitution failed:
/usr/include/boost/iostreams/detail/path.hpp: In substitution of ‘template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::external_string_type*) [with Path = boost::iostreams::file_descriptor_source]’:
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: required from ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:57:14: error: no type named ‘external_string_type’ in ‘class boost::iostreams::file_descriptor_source’
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:52:5: note: boost::iostreams::detail::path::path(const char*)
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
/usr/include/boost/iostreams/detail/path.hpp:52:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const char*’
/usr/include/boost/iostreams/detail/path.hpp:49:5: note: boost::iostreams::detail::path::path(const string&)
path(const std::string& p) : narrow_(p), wide_(), is_wide_(false) { }
^
/usr/include/boost/iostreams/detail/path.hpp:49:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const string& {aka const std::basic_string<char>&}’
/usr/include/boost/iostreams/detail/path.hpp:46:5: note: boost::iostreams::detail::path::path()
path() : narrow_(), wide_(), is_wide_(false) { }
^
/usr/include/boost/iostreams/detail/path.hpp:46:5: note: candidate expects 0 arguments, 1 provided
make: *** [src/boostPopenHandler.o] Error 1
Upvotes: 4
Views: 2042
Reputation: 2034
Oh, you should be first declaring a file_descriptor_source as in
boost::iostreams::file_descriptor_source fds(fd);
and then comes your stream buffer
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> bis(fds);
Edit:
Sorry for the confusion, that ctor with an int parameter is deprecated and it seems that you do not have that ctor because otherwise your code would compile perfectly. That is why the above code i supplied needs a second mandatory parameter of either boost::iostreams::never_close_handle
or boost::iostreams::close_handle
So it should read
boost::iostreams::file_descriptor_source fds(fd, boost::iostreams::close_handle);
otherwise you would still get that error. And same fix goes with the file_descriptor_sink also.
Now as for how you should read the errors:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]’:
Says that it tried to instantiate a file_descriptor_source with a template parameter choice of
[with Path = char; std::ios_base::openmode = std::_Ios_Openmode]
Since you only supplied an integer, the compiler tried to match that version of the ctor and failed to make the conversion.
Upvotes: 5
Reputation: 171403
You don't need Boost for this.
wanted to convert a *FILE (such as returned by popen()) to a iostream
Use pstreams instead (disclaimer, I wrote it, if that matters).
Some compilers provide extensions to create a streambuf from a C file without needing Boost, e.g. with GCC:
#include <ext/stdio_filebuf.h>
...
__gnu_cxx::stdio_filebuf<char> fb(fp, std::ios::out);
std::ostream os(&fb);
Upvotes: 0