2011-01-25 15 views
8

我正在嘗試爲C庫創建一個Haskell包裝器。底層結構太複雜,不能用明確的類型來表示,除了在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。因此,我可以完成我打電話get_struct之前ptr目標是通過使用peek

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

這感覺就像一個黑客,但。

有沒有辦法讓空數據聲明被認爲是Storable沒有定義實例?

+2

這是一個破解。你永遠不會爲內部指針分配空間;你只是指着隨機記憶。這種方式存在段錯誤。 – 2011-01-25 15:39:21

+0

所以如果我合法地想要一個指針指針,我應該使用兩個`alloca`調用,然後`戳一個指針到另一個,對吧? – zmthy 2011-01-25 22:59:26

回答

6

如果你不知道它有多大,你就不能分配一些東西。函數是否會忽略它的參數?然後傳入一個空指針。否則,您需要爲結構實際分配足夠的空間 - 不要通過分配零字節或指針大小的緩衝區來削減角點,因爲被調用的函數將寫入緩衝區末尾,從而破壞內存。

要麼完成數據聲明,要麼寫入具有適當大小和對齊值的Storable實例;沒有辦法以某種形式提供大小/對齊數據。

2

下面是另一種可能適用於您的方法。我假設你可以訪問所有定義你需要分配的對象的C頭文件。如果這是真的,你可以編寫一層用於分配和釋放C對象的C代碼。然後你的Haskell代碼可以調用這些C函數,而Haskell代碼不需要知道指針背後的內容。當Haskell的垃圾收集器知道不再需要這些對象時,Haskell也可以自動調用該空閒代碼。