Haskell FFI для рекурсивной структуры и объединения C

#haskell #ffi

#haskell #ffi

Вопрос:

Я пытаюсь написать привязку Haskell FFI для некоторых структур C. Пример приведен ниже:

 typedef struct s0{int a; 
                  union{unsigned char b; 
                        struct s0*c; 
                        struct{unsigned char d[1];
                         }; };}*S;
  

Мой вопрос в том, как написать привязку для нее в формате chs (для c2hs) или hsc (для hsc2hs)? Я просмотрел руководства по c2hs, но либо не получил достаточной информации, либо не понял ее таким образом, который помог бы мне написать файл chs для приведенного выше определения.

Я могу генерировать привязки haskell с помощью инструмента HSFFIG, но он использует пользовательский метод доступа HSFFIG.Доступ к полю.Доступ к полю для определения привязок. Я предпочитаю писать привязки, которые используют основные библиотеки haskell FFI, а не библиотеки сторонних производителей.

Следовательно, этот вопрос о том, как написать привязку для рекурсивной структуры выше в формате hsc или формате chs, который использует только основные библиотеки FFI.

Фактическое определение более сложное, но как только я выясню, как написать приведенное выше определение структуры для инструментов c2hs или hsc2hs, я смогу перейти оттуда. Я знаю, что сохраняемые экземпляры также должны быть определены для внутреннего объединения и структуры, но я не знаю, как написать оболочки для рекурсивного определения, подобного приведенному выше. В частности, как получить доступ к внутренней структуре / объединению из внешней структуры? Я просмотрел определения HSFFIG, но методы доступа — это методы доступа, определенные HSFFIG. Итак, я не смог понять, как перевести это в определение chs, которое использует только основные библиотеки FFI.

Вопросы, которые я видел в StackOverflow, похоже, касаются более простых определений. Если где-то еще есть подобный ответ, я буду признателен за указания.

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

1. Вам действительно нужно что-то делать с данными? Возможно, вам сойдет с рук использование типа данных void

2. Да, мне действительно нужно разобраться с данными. Указатель на вышеупомянутую структуру передается другой функции FFI C в качестве одного из аргументов, и эта функция возвращает значение struct.

3. не похоже, что вас волнуют данные.

4. Возвращаемое значение struct будет использоваться в коде haskell после извлечения соответствующего значения и после использования соответствующей функции доступа. Итак, это действительно имеет значение. Производительность FFI (и, следовательно, объем сортируемых данных) на самом деле не имеет значения.

5. Вы хотите читать и записывать данные C напрямую или маршалировать к / из данных Haskell? Маршалинг копирует всю структуру данных, но проще в использовании.

Ответ №1:

Вы не можете создать эквивалентную структуру данных ни в c2hs, ни в hsc2hs. Однако вы можете выполнить свой собственный маршалинг в c2hs, лишь немного поработав.

 data MyType = Next MyType | MyChar Char | MyString String | MyEnd
  

Затем используйте функциональность указателя newtype от hsc2hs, чтобы объявить указатель для MyType (т.Е. s0). Затем напишите явную функцию, используя средства доступа hsc2hs, чтобы рекурсивно обходить вашу структуру и создавать вашу структуру Haskell. На каждом шаге вы проверяете, нажали ли вы нулевой указатель, и если да, возвращаете MyEnd (или, в зависимости от кодировки данных, просто проверяете, является ли значение int, указывающее тип в объединении, отрицательным или любым другим), в противном случае продолжайте анализировать все, что у вас есть, и, если это указатель, продолжайте рекурсивно.

Вы могли бы сделать почти то же самое и с hsc2hs.