2012-02-07 87 views
2

我有一個向量列表 - 這組類型是已知的並且是固定的 - 比如說,CIntCChar。該列表在編譯時未知 - 組合將在運行時從配置文件中確定。例如,我們可能決定我們需要將兩個向量傳遞給C函數:一個CInt長度爲10的向量,一個CChar長度爲50的向量。至於C函數如何解釋它們,我可以通過傳遞向量編碼類型每個矢量(例如,0 =>CInt,1 =>CChar),並且每個矢量的矢量編碼長度通過(10,50)。將混合可存儲矢量傳遞給C函數

我想弄清楚的是如何生成混合向量的矢量(僅用於傳遞給C)。我嘗試了一個類似下面的玩具解決方案(它模擬相同的想法 - 生成混合類型的Ptr的可存儲矢量 - 在實際代碼中,每個Ptr將指向另一個可存儲矢量)。它由於類型錯誤而失敗 - 我懷疑它與之前在另一個question中指出的exhtentially qualified類型有關。由於我使用Storable實例傳遞給C FFI,我想我不能包裝類型(沒有定義另一個可存儲的實例)。

{-# LANGUAGE BangPatterns, GADTs #-} 
import Data.Vector.Storable as SV 
import Foreign.C.Types (CChar, CInt) 
import GHC.Int (Int32) 
import Foreign.Marshal.Alloc 
import Foreign.Ptr (Ptr) 

mallocInt :: IO (Ptr CInt) 
mallocInt = malloc 

mallocChar :: IO (Ptr CChar) 
mallocChar = malloc 

main = do 
    a <- mallocInt 
    b <- mallocChar 
    let c = SV.fromList [a,b] 
    return() 

錯誤ghci的7.4.1:

test.hs:17:26: 
    Couldn't match expected type `CInt' with actual type `CChar' 
    Expected type: Ptr CInt 
     Actual type: Ptr CChar 
    In the expression: b 
    In the first argument of `fromList', namely `[a, b]' 
Failed, modules loaded: none. 

我會很高興就如何解決上述問題的指針。我可以使用Data.Vector.Storable.Mutable.new和unsafeWrite編寫自定義矢量填充函數,但仍然需要適應混合類型。

回答

5

像C,你需要能夠將其存儲在一個通用的陣列之前投下了char *int *void *。因此,在將其插入矢量中之前,將您的Ptr CChar和轉換爲Ptr()

您可以通過使用Foreign.Ptr.castPtr功能,像這樣將指針:

intPtr :: Ptr CInt 
intPtr = undefined -- dummy value 

voidPtr :: Ptr() 
voidPtr = castPtr intPtr 
+0

可否請你也展示瞭如何投'PTR CChar'到'PTR()的例子'在Haskell?使用Unsafecoerce? – Sal 2012-02-07 19:13:32

+0

@sal,當然可以!我添加了一些示例代碼。 – dflemstr 2012-02-07 19:16:21

+0

非常感謝。 – Sal 2012-02-07 19:18:31