Передача смешанных хранимых векторов в функцию C - PullRequest
2 голосов
/ 07 февраля 2012

У меня есть список векторов - набор типов известен и фиксирован - скажем, CInt и CChar. Список неизвестен во время компиляции - состав будет определяться из файла конфигурации во время выполнения. Например, мы можем решить, что нам нужно передать два вектора в функцию C: один CInt вектор длины 10, один CChar вектор длины 50. Что касается того, как функция C интерпретирует их, я могу обработать эту логику с помощью передача типов кодирования вектора каждого вектора (скажем, 0 => CInt, 1 => CChar) и длины кодирования вектора каждого пройденного вектора (10,50).

То, что я пытаюсь выяснить, - это как создать вектор смешанных векторов (только для передачи в C). Я попробовал игрушечное решение, подобное приведенному ниже (оно моделирует ту же идею - генерирование хранимого вектора Ptr смешанных типов - в реальном коде каждый Ptr будет указывать на другой хранимый вектор). Это не удалось из-за ошибки типа - я подозреваю, что это связано с экзистенциально определенными типами, на которые ehird указывал ранее в другом вопросе , который я задавал ранее. Поскольку я использую экземпляр 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 Ответ

5 голосов
/ 07 февраля 2012

Как и в C, вам нужно привести char * и int * к void *, прежде чем вы сможете сохранить его в универсальном массиве. Итак, приведите ваши Ptr CChar и Ptr CInt к Ptr () перед тем, как вставить их в вектор.

Вы можете привести указатель, используя функцию Foreign.Ptr.castPtr, например:

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

voidPtr :: Ptr ()
voidPtr = castPtr intPtr
...