Преобразовать ДЕСКРИПТОР в дескриптор

#winapi #haskell #io

#winapi #хаскелл #io #haskell

Вопрос:

Я хочу создать анонимный канал в Windows, используя CreatePipe WinAPI через FFI. Это даст мне HANDLE (тип из Win32 пакета haskell), но я хотел бы получить обычный haskell Handle , чтобы я мог использовать на нем стандартные функции ввода-вывода haskell. Итак, мне нужна функция типа:

 win32handleToStandardHandle :: HANDLE -> IO Handle
  

Как я могу это реализовать?

В Linux я могу использовать System.Posix.IO fdToHandle функцию для преобразования между FD типом, используемым системными вызовами Linux, и стандартным типом haskell. Но, похоже, такой функции для Windows нет.

Комментарии:

1. Похоже, что HANDLE это просто синоним типа: type HANDLE = Ptr () . Я понятия не имею, как ответить на ваш вопрос, но это не дает функции преобразования особых возможностей для работы… :

2. Я вижу, что HANDLE определяется как type HANDLE = Ptr () , в то время как Handle является алгебраическим типом данных, представляющим либо одиночный дескриптор, либо дуплексный дескриптор для RW, который сам по себе реализуется сложной структурой записи. Существует ли много функций для получения информации о HANDLE из Win32 API? Вам понадобятся такие вещи, как режим буферизации, текущий буфер символов, кодировка текста и т.д. Возможно, это можно написать самостоятельно, но я бы предположил, что исправление может быть несколько утомительным.

Ответ №1:

Даже в Windows стандартная реализация файлов в System.IO использует дескриптор файла, а не win32 HANDLE . Эти файловые дескрипторы предоставляются средой выполнения C, а не Windows. Для преобразования HANDLE в файловый дескриптор среда выполнения предоставляет _open_osfhandle функцию. GHC использует MinGW в Windows, но MinGW не предоставляет собственную среду выполнения C, поэтому Haskell EXEs использует msvcrt.dll .

Используйте FFI для импорта _open_osfhandle . Используйте это, чтобы преобразовать ваш HANDLE в файловый дескриптор, а затем вызвать fdToHandle , который, похоже, находится в GHC.IO.Handle.FD .

На самом деле я этого не пробовал.

Комментарии:

1. MinGW не предоставляет собственную среду выполнения C, не так ли? Большинство людей, похоже, ссылаются на (неподдерживаемый!) msvcrt.dll , таким образом, документы MS настолько близки, насколько вы собираетесь получить.

2. @HarryJohnston Ты прав. Haskell EXEs импортирует стандартные функции C из msvcrt.dll .

3. Вы правы, что fdToHandle живет в GHC.IO.Handle.FD . Однако он принимает аргумент типа FD , который определен в недоступном модуле GHC.IO.FD . Но, как вы говорите, HANDLE функции ввода-вывода GHC на самом деле не поддерживаются, поэтому я просто напишу функции чтения / записи напрямую для HANDLE , это намного проще.

4. @bennofs Есть два разных типа, которые называются FD . Незащищенный вариант несколько сложен, но fdToHandle использует System.Posix.Internals.FD всего лишь CInt .

5. @bennofs: обратите внимание, что у каждого Handle есть связанный HANDLE , потому что без него процесс фактически не может выполнять какие-либо операции ввода-вывода. Единственное отличие здесь в том, что вы хотите использовать HANDLE , который вы открыли сами, а не тот, который Haskell (и среда выполнения C) открыли для вас.