Вопрос

Я пытаюсь создать обертку Haskell для библиотеки C. Базовые структуры слишком сложны, чтобы выразить как явные типы, и я на самом деле не использую их, кроме прохождения между функциями C, поэтому я использую EmptyDataDecls Чтобы GHC разрабатывал это для меня.

Что мне нужно, так это указатель на один из этих типов данных, но когда я пытаюсь создать один с alloca он жалуется, что данные не имеют типа Storable. Анкет Например:

{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}

module Main where

import Foreign.Marshal.Alloc
import Foreign.Ptr

data Struct

foreign import ccall "header.h get_struct"
    get_struct :: Ptr Struct -> IO ()

main = alloca $ \ptr -> get_struct ptr

GHC не скомпилирует это, сказав, что нет экземпляра для Storable Struct. Анкет Я мог бы реализовать это сам:

instance Storable Struct where
    sizeOf _    = ...
    alignment _ = ...

Но это приближается к победе над целью - я не хочу определять такие вещи, если мне все равно, что в структуре.

Я заметил, что указатель на указатель работает нормально, потому что Ptr Класс Storable. Анкет Так что я могу выполнить то, к чему я стремлюсь peek на ptr перед звонком get_struct:

main = alloca $ \ptr -> do
  ptr <- peek ptr
  get_struct ptr

Это похоже на взлом.

Есть ли способ получить пустые объявления данных Storable без определения экземпляра?

Это было полезно?

Решение

Вы не можете что -то выделить, если не знаете, насколько это велика. Собирается ли функция игнорировать свой аргумент? Затем пройдите в нулевом указателе. В противном случае, вам нужно на самом деле выделить достаточно места для структуры-не вырезать углы, выделяя буфер с нулевым или размером с указатель, так как тогда вызывающаяся функция будет писать после конца вашего буфера, повреждающего память.

Либо заканчивайте объявление данных, либо напишите художественный экземпляр с правильным размером и значениями выравнивания; В той или иной форме нет способа предоставить данные о размерах/выравнивании.

Другие советы

Вот еще один подход, который может сработать для вас. Я предполагаю, что у вас есть доступ ко всем файлам заголовка C, которые определяют объекты, необходимые для распределения. Если это правда, вы можете написать тонкий слой C -кода для распределения и освобождения объектов C. Ваш код Haskell может затем вызвать эти C -функции без кода Haskell, когда -либо не нужно знать, что стоит за указателями. Haskell также может автоматически вызвать бесплатный код, когда коллекционер мусора Haskell знает, что объекты больше не нужны.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top