Сохраняемое пустое объявление данных - PullRequest
9 голосов
/ 25 января 2011

Я пытаюсь создать оболочку 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 без определения экземпляра?

Ответы [ 2 ]

6 голосов
/ 25 января 2011

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

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

2 голосов
/ 26 января 2011

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

...