Ich versuche, eine Haskell vector von beliebig rechts verschachtelten Paaren (dh Vector (Int64, (Int64, (...)))
) als 2-d-Array in C (dh int64_t**
), zuerst indiziert als die Vektorkomponente, dann die Tupel-Komponente .Marshalling Vektoren von Zeigern
Hier ist meine C-Funktion:
void test(int64_t** y, int32_t vecSize int16_t tupSize, int64_t* tup)
{
printf("Tup vals: ");
for(int i = 0; i < tupSize; i++) {
printf("%" PRId64 ",",tup[i]);
}
printf("\n");
printf("vec\n");
for(int i = 0; i < vecSize; i++) {
printf("%d: (", i);
for(int j = 0; j < tupSize; j++) {
printf("%" PRId64 ",", y[i][j]);
}
printf(")\n");
}
}
Auf der Haskell Seite habe ich:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Int
import Data.Vector.Storable (Vector, singleton, unsafeWith)
import Foreign.Marshal.Utils (with)
import Foreign.Ptr
import Foreign.Storable (Storable (..))
foreign import ccall unsafe "test" test :: Ptr (Ptr Int64) -> Int64 -> Int16 -> Ptr Int64 -> IO()
-- instance assumes right-nested pairs, but not enforced at type level
instance (Storable a, Storable b)
=> Storable (a,b) where
sizeOf _ = (sizeOf (undefined :: a)) + (sizeOf (undefined :: b))
alignment _ = max (alignment (undefined :: a)) (alignment (undefined :: b))
peek p = do
a <- peek (castPtr p :: Ptr a)
b <- peek (castPtr (plusPtr p (sizeOf a)) :: Ptr b)
return (a,b)
poke p (a,b) = do
poke (castPtr p :: Ptr a) a
poke (castPtr (plusPtr p (sizeOf a)) :: Ptr b) b
main :: IO()
main = do
let tup = (10,11) :: (Int64, Int64)
vec = singleton (2,3) :: Vector (Int64, Int64)
with tup $ \tptr ->
unsafeWith vec $ \vptr ->
test (castPtr vptr) 1 2 (castPtr tptr)
Dieser druckt
Moduli: 10,11,
vec
Segmentation fault
, die mich führt zu glauben, dass meine Storable (a,b)
Instanz in Ordnung ist : Ich bekomme einen Zeiger für (Int64,Int64)
, dann umwandeln es Ptr Int64
, und lesen Sie die Daten in C gut. So ist die Frage, was mit dem Vektor falsch läuft? Ich versuche, das gleiche zu tun: Erstellen Sie eine Vector (Int64, Int64)
, erhalten Sie einen Zeiger des Typs Ptr (Int64, Int64)
dafür, und werfen Sie es auf eine Ptr (Ptr Int64)
. Warum erhalte ich einen Segmentfehler, wenn ich versuche, auf das Array in C zuzugreifen, und was ist der richtige Weg, um diese Daten zu übertragen?
Recall, dass in C, ein Array von ints in einen Zeiger auf int Zerfall kann, und die ein Array von Arrays von ints kann in einen Zeiger auf Array von ints Zerfall, sondern _not_ zu einem Zeiger auf den Zeiger zu int. Sie können kein 'int a [3] [5]' übergeben, wo ein 'int ** a 'erwartet wird, aber Sie können auch ein' int (* a) [5]' angeben. – chi