9

C ライブラリの Haskell ラッパーを作成しようとしています。基礎となる構造体は複雑すぎて明示的な型として表現できず、実際には C 関数間の受け渡し以外には使用しないのでEmptyDataDecls、GHC に解決してもらうために使用しています。

必要なのは、これらのデータ型のいずれかへのポインターですが、それを使用して作成しようとするallocaと、データが type ではないと不平を言い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 _ = ...

しかし、それは目的を打ち負かすことに近づいています-構造体の内容を気にしないのであれば、そのようなものを定義する必要はありません。

クラスPtrStorable. したがって、呼び出す前にpeekonを使用することで、目的を達成できます。ptrget_struct

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

ただし、これはハックのように感じます。

Storableインスタンスを定義せずに空のデータ宣言を考慮する方法はありますか?

4

2 に答える 2

6

大きさがわからないものは割り振ることができません。関数はその引数を無視するだけですか? 次に、null ポインターを渡します。それ以外の場合は、実際に構造体に十分なスペースを割り当てる必要があります。0 バイトまたはポインター サイズのバッファーを割り当てることで手抜きをしないでください。呼び出された関数がバッファーの末尾を超えて書き込み、メモリが破損するためです。

データ宣言を終了するか、適切なサイズと配置値で Storable インスタンスを書き込みます。サイズ/配置データを何らかの形で提供する方法はありません。

于 2011-01-25T14:37:07.933 に答える
2

これがあなたのために働くかもしれない別のアプローチです。割り当てる必要のあるオブジェクトを定義するすべての C ヘッダー ファイルにアクセスできると仮定します。そうであれば、C オブジェクトを割り当てて解放するための C コードの薄い層を書くことができます。Haskell コードは、ポインターの背後にあるものを知る必要なく、これらの C 関数を呼び出すことができます。Haskell のガベージ コレクターがオブジェクトが不要になったことを認識した場合、Haskell は自動的にフリー コードを呼び出すこともできます。

于 2011-01-26T02:16:19.693 に答える