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



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

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

与C中一样,您需要将char *int *强制转换为void *,然后才能将其存储在泛型数组中。因此,将Ptr CCharPtr CInt强制转换为Ptr (),然后再将其插入向量中。

您可以使用Foreign.Ptr.castPtr函数来投射指针,如下所示:

intPtr :: Ptr CInt
intPtr = undefined -- dummy value
voidPtr :: Ptr ()
voidPtr = castPtr intPtr

最新更新