I have a list of vectors - the set of types is known and fixed - let us say, CInt
and CChar
. The list is unknown at compile time - the composition will be determined from a configuration file at run-time. For example, we might decide we need to pass two vectors to C
function: One CInt
vector of length 10, one CChar
vector of length 50. As to how C function interprets them, I can handle that logic by passing a vector encoding types of each vector (say, 0 => CInt
, 1 => CChar
), and a vector encoding length of each vector passed (10,50).
What I am trying to figure out is how to generate a vector of mixed vectors (just for passing to C). I tried a toy solution like the one below (it models the same idea - generating a storable vector of Ptr
of mixed types - in actual code, each Ptr will point to another Storable vector). It failed because of type error - I suspect it is related to existentially qualified types that ehird pointed out before in another question I asked earlier. Since I am using Storable instance for passing to C FFI, I guess I can't wrap the types (without defining another storable instance).
{-# 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 ()
Error in 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.
I will appreciate pointers on how to solve the above problem. I could write a custom vector filling function using Data.Vector.Storable.Mutable.new and unsafeWrite, but still I will need to fit the mixed types.
Like in C, you need to cast a char *
and int *
to a void *
before being able to store it in a generic array. So, cast your Ptr CChar
and Ptr CInt
to a Ptr ()
before inserting it into a vector.
You can cast a pointer by using the Foreign.Ptr.castPtr
function like so:
intPtr :: Ptr CInt
intPtr = undefined -- dummy value
voidPtr :: Ptr ()
voidPtr = castPtr intPtr