将混合可存储向量传递给C函数

时间:2012-02-07 18:47:13

标签: haskell ffi storable

我有一个向量列表 - 已知并修复了类型集 - 让我们说,CIntCChar。该列表在编译时是未知的 - 组合将在运行时从配置文件中确定。例如,我们可能决定需要将两个向量传递给C函数:一个长度为10的CInt向量,一个长度为50的CChar向量。至于C函数如何解释它们,我可以通过传递每个向量的向量编码类型(例如,0 => CInt,1 => CChar)来处理该逻辑,并且传递每个向量的向量编码长度(10, 50)。

我想弄清楚的是如何生成混合向量的向量(仅用于传递给C)。我尝试了类似下面的玩具解决方案(它模拟了相同的想法 - 生成Ptr混合类型的可存储向量 - 在实际代码中,每个Ptr将指向另一个可存储向量)。它因类型错误而失败 - 我怀疑它与先前在我之前提到的另一个question中指出的存在性合格类型有关。由于我使用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编写自定义矢量填充函数,但我仍然需要适应混合类型。

1 个答案:

答案 0 :(得分:5)

与C类似,您需要将char *int *转换为void *,然后才能将其存储在通用数组中。因此,请先将Ptr CCharPtr CInt投放到Ptr (),然后再将其插入到矢量中。

您可以使用Foreign.Ptr.castPtr函数来强制转换指针,如下所示:

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

voidPtr :: Ptr ()
voidPtr = castPtr intPtr