我试图将任意右嵌套对(即Vector (Int64, (Int64, (...)))
)的Haskell vector表示为C中的2-d数组(即int64_t**
),首先索引为向量组件,然后是元组组件。
这是我的C函数:
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");
}
}
在Haskell方面,我有:
{-# 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)
打印
Moduli: 10,11,
vec
Segmentation fault
这让我认为我的Storable (a,b)
实例很好:我正在获取(Int64,Int64)
的指针,然后将其转换为Ptr Int64
,并在C中读取数据就好了那么问题是向量出了什么问题?我正在尝试做同样的事情:创建一个Vector (Int64, Int64)
,为它获取一个类型为Ptr (Int64, Int64)
的指针,并将其转换为Ptr (Ptr Int64)
。当我尝试在C中访问数组时,为什么会出现段错误,以及编组这些数据的正确方法是什么?
答案 0 :(得分:4)
您并未在双方使用相同的数据格式。你的Haskell代码在向量的所有元组中生成一个包含所有值的平面数组,而你的C代码需要一个指针数组,一个用于向量的每个元素,指向其中的值元组。
如果你可以像这样声明你的C函数(现在这可能是有效的C,我也不知道)
void test(int64_t (*y)[tupSize], int32_t vecSize, int16_t tupSize, int64_t *tup)
然后C将使用与Haskell相同的布局。否则,您可以使用
手动编制索引// SINGLE pointer |
// v
void test(int64_t *y, int32_t vecSize, int16_t tupSize, int64_t *tup)
...
printf("%" PRId64 ",", y[i*tupSize+j]);