¿Hay un equivalente de Windows para fdopen para HANDLEs?

En Unix, si tiene un descriptor de archivo (por ejemplo, desde un socket, pipe o hereditario de su proceso principal), puede abrir un flujo de E / S FILE* en fdopen(3) con fdopen(3) .

¿Hay un equivalente en Windows para HANDLE s? Si tiene un HANDLE que se heredó de su proceso principal (diferente de stdin, stdout o stderr) o un conducto de CreatePipe , ¿es posible obtener un flujo de FILE* almacenado en él? MSDN documenta _fdopen , pero funciona con descriptores de archivos enteros devueltos por _open , no _open genéricas.

Desafortunadamente, HANDLE s son bestias completamente diferentes de FILE* sy descriptores de archivos. En última instancia, el CRT maneja los archivos en términos de HANDLE y asocia esos HANDLE a un descriptor de archivo. Esos descriptores de archivo a su vez retrocede el puntero de estructura por FILE* .

Afortunadamente, hay una sección en esta página MSDN que describe las funciones que “proporcionan una forma de cambiar la representación del archivo entre una estructura FILE , un descriptor de archivo y un identificador de archivo Win32″:

  • _fdopen , _wfdopen : asocia una secuencia con un archivo que se abrió previamente para E / S de bajo nivel y devuelve un puntero a la secuencia abierta.
  • _fileno : Obtiene el descriptor de archivo asociado a una secuencia.
  • _get_osfhandle : devolver el identificador de archivo del sistema operativo asociado con el descriptor de archivo C en tiempo de ejecución existente
  • _open_osfhandle : _open_osfhandle archivo de tiempo de ejecución de Associates C con un identificador de archivo de sistema operativo existente.

Parece que lo que necesitas es _open_osfhandle seguido de _fdopen para obtener un FILE* de un HANDLE .

Aquí hay un ejemplo de HANDLE s obtenido de CreateFile() . Cuando lo probé, muestra los primeros 255 caracteres del archivo “test.txt” y agrega “— Hello World! —” al final del archivo:

 #include  #include  #include  #include  int main() { HANDLE h = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(h != INVALID_HANDLE_VALUE) { int fd = _open_osfhandle((intptr_t)h, _O_APPEND | _O_RDONLY); if(fd != -1) { FILE* f = _fdopen(fd, "a+"); if(f != 0) { char rbuffer[256]; memset(rbuffer, 0, 256); fread(rbuffer, 1, 255, f); printf("read: %s\n", rbuffer); fseek(f, 0, SEEK_CUR); // Switch from read to write const char* wbuffer = " --- Hello World! --- \n"; fwrite(wbuffer, 1, strlen(wbuffer), f); fclose(f); // Also calls _close() } else { _close(fd); // Also calls CloseHandle() } } else { CloseHandle(h); } } } 

Esto debería funcionar también para tuberías.