2012-02-07 81 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