#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.