Básicamente estoy buscando una versión C ++ de fdopen (). Investigué un poco sobre esto y es una de esas cosas que parece que debería ser fácil, pero resulta ser muy complicado. ¿Me estoy perdiendo algo en esta creencia (es decir, realmente es fácil)? Si no es así, ¿hay una buena biblioteca en algún lugar para manejar esto?
EDITAR: Moví mi solución de ejemplo a una respuesta separada.
c++
posix
fstream
file-descriptor
BD en Rivenhill
fuente
fuente
mmap
con el archivo y exponer su contenido como matriz de bytes.Respuestas:
De la respuesta dada por Éric Malenfant:
Según las observaciones anteriores y mi investigación a continuación, hay un código de trabajo en dos variantes; uno para libstdc ++ y otro para Microsoft Visual C ++.
libstdc ++
Hay una
__gnu_cxx::stdio_filebuf
plantilla de clase no estándar que heredastd::basic_streambuf
y tiene el siguiente constructorcon descripción Este constructor asocia un búfer de flujo de archivos con un descriptor de archivo POSIX abierto.
Lo creamos pasando el identificador POSIX (línea 1) y luego lo pasamos al constructor de istream como basic_streambuf (línea 2):
Microsoft Visual C ++
Solía haber una versión no estándar del constructor de ifstream que tomaba el descriptor de archivo POSIX, pero falta tanto en los documentos actuales como en el código. Hay otra versión no estándar del constructor de ifstream que toma FILE *
y no está documentado (ni siquiera pude encontrar ninguna documentación antigua donde estaría presente). Lo llamamos (línea 1) y el parámetro es el resultado de llamar a _fdopen para obtener la secuencia C FILE * del identificador del archivo POSIX.
fuente
std::cout
implementación es una buena idea. Me pregunto cuál es la diferencia entrestdio_filebuf
ystdio_sync_filebuf
.AFAIK, no hay forma de hacer esto en C ++ estándar. Dependiendo de su plataforma, su implementación de la biblioteca estándar puede ofrecer (como una extensión no estándar) un constructor fstream tomando un descriptor de archivo (este es el caso de libstdc ++, IIRC) o
FILE*
como entrada.Otra alternativa sería usar un dispositivo boost :: iostreams :: file_descriptor , que podría envolver en un boost :: iostreams :: stream si desea tener una interfaz std :: stream.
fuente
Es muy probable que su compilador ofrezca un constructor fstream basado en FILE, aunque no sea estándar. Por ejemplo:
Pero hasta donde yo sé, no hay una forma portátil de hacer esto.
fuente
Parte de la motivación original (no declarada) de esta pregunta es tener la capacidad de pasar datos entre programas o entre dos partes de un programa de prueba utilizando un archivo temporal creado de forma segura, pero tmpnam () arroja una advertencia en gcc, así que quería para usar mkstemp () en su lugar. Aquí hay un programa de prueba que escribí basado en la respuesta dada por Éric Malenfant pero usando mkstemp () en lugar de fdopen (); esto funciona en mi sistema Ubuntu con las bibliotecas Boost instaladas:
fuente
De hecho, es bastante fácil. Nicolai M. Josuttis ha publicado
fdstream
junto con su libro The C ++ Standard Library - A Tutorial and Reference . Puede encontrar la implementación de la línea 184 aquí .fuente
Probé la solución propuesta anteriormente para libstdc ++ por Piotr Dobrogost, y descubrí que tenía un defecto doloroso: debido a la falta de un constructor de movimiento adecuado para istream, es muy difícil sacar el objeto istream recién construido de la función de creación . Otro problema con él es que filtra un objeto FILE (incluso aunque no sea el descriptor de archivo posix subyacente). Aquí hay una solución alternativa que evita estos problemas:
La llamada a posix_fadvise () demuestra un uso potencial. También tenga en cuenta que el ejemplo usa static_assert y usa C ++ 11, aparte de eso, debería compilarse bien en el modo C ++ 03.
fuente
Tengo entendido que no hay asociación con punteros de ARCHIVO o descriptores de archivo en el modelo de objetos de iostream de C ++ para mantener el código portátil.
Dicho esto, vi en varios lugares referirse a mds-utils o boost para ayudar a cerrar esa brecha.
fuente