Передача смешанных хранимых векторов в функцию 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