Передача смешанных хранимых векторов в функцию C

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

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

Решение

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

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

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

voidPtr :: Ptr ()
voidPtr = castPtr intPtr
Другие вопросы по тегам