Existe um equivalente do Windows para fdopen para HANDLEs?

No Unix, se você tiver um descritor de arquivo (por exemplo, de um soquete, canal ou herdado de seu processo pai), você pode abrir um stream de E / S FILE* em buffer com fdopen(3) .

Existe um equivalente no Windows para HANDLE s? Se você tiver um HANDLE herdado de seu processo pai (diferente de stdin, stdout ou stderr) ou um pipe de CreatePipe , será possível obter um stream FILE* armazenado em buffer a partir dele? O MSDN documenta _fdopen , mas funciona com descritores de arquivos inteiros retornados por _open , e não por HANDLE genéricos.

Infelizmente, HANDLE s são bestas completamente diferentes dos descritores de arquivos e arquivos. O CRT finalmente lida com arquivos em termos de HANDLE e associa esses HANDLE s a um descritor de arquivo. Esses descritores de arquivo, por sua vez, retornam o ponteiro de estrutura por FILE* .

Felizmente, há uma seção nesta página do MSDN que descreve funções que “fornecem uma maneira de alterar a representação do arquivo entre uma estrutura FILE , um descritor de arquivo e um identificador de arquivo Win32″:

  • _fdopen , _wfdopen : associa um stream a um arquivo que foi aberto anteriormente para E / S de baixo nível e retorna um ponteiro para o stream aberto.
  • _fileno : obtém o descritor de arquivo associado a um stream.
  • _get_osfhandle : Retorna o identificador de arquivo do sistema operacional associado ao descritor de arquivo de tempo de execução C existente
  • _open_osfhandle : associa o descritor de arquivo de tempo de execução C a um identificador de arquivo do sistema operacional existente.

Parece que o que você precisa é _open_osfhandle seguido de _fdopen para obter um FILE* de um HANDLE .

Aqui está um exemplo envolvendo HANDLE obtido de CreateFile() . Quando eu testei, ele mostra os primeiros 255 caracteres do arquivo “test.txt” e acrescenta “— Hello World! —” no final do arquivo:

 #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); } } } 

Isso deve funcionar para tubos também.