如何使用 Haskell inline-c 查看二维数组
How to peek 2d array with Haskell inline-c
你好,我想和 2d arrays
:
一起工作
--2d arrays
cArray :: IO (Ptr (Ptr CDouble))
cArray = do
x <- [C.block| double (*)[2] {
double (*ptd)[2] = malloc(sizeof(double[2][2]));
ptd[0][0] = 1.78;
ptd[0][1] = 1.68;
ptd[1][0] = 1.58;
ptd[1][1] = 1.48;
printf("the firstelement is: %f\n", ptd[1][1]);
return ptd;
}|]
return x
然后在另一个函数中:
e <- cArray :: IO (Ptr (Ptr CDouble))
e1 <- peekElemOff e 0 :: IO (Ptr CDouble)
e2 <- peekElemOff e1 0 :: IO CDouble
print e2
这总是给出段错误。
对于一维数组,我没有问题。
有人能给我提示吗?
C 二维数组实际上只是一个一维数组,在其范围内,编译器跟踪行长度以计算二维索引。如果转换为 Ptr (Ptr CDouble)
,此大小信息将丢失。 C 二维数组不同于数组数组的二维数组——后者通常是一个 锯齿状数组,但你也可以仅通过两次分配更有效地获得这样的数组——一个对于内容,一个是指向每一行的指针。
cArray :: IO (Ptr (Ptr CDouble))
cArray = [C.block| double** {
int n = 2, m = 2;
double* arr = malloc(sizeof(double[n*m]));
double** ptd = malloc(sizeof(double*[n]));
for (int i=0; i<2; ++i)
ptd[i] = &(arr[i*m]);
ptd[0][0] = 1.78;
ptd[0][1] = 1.68;
ptd[1][0] = 1.58;
ptd[1][1] = 1.48;
printf("the firstelement is: %f\n", ptd[0][0]);
return ptd;
}|]
正如您自己所记得的,C 分配的内存最终需要再次清理。 Haskell 垃圾收集器本身无法为您完成此操作,但您可以使用 ForeignPtr
而不是原始 Ptr
.
来挂钩它
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
import Language.C.Inline as C
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable
C.include "<stdio.h>"
C.include "<stdlib.h>"
cArray :: IO (ForeignPtr (Ptr CDouble))
cArray = do
x <- [C.block| double** {
int n = 2, m = 2;
double* arr = malloc(sizeof(double[n*m]));
double** ptd = malloc(sizeof(double*[n]));
for (int i=0; i<2; ++i)
ptd[i] = &(arr[i*m]);
ptd[0][0] = 1.78;
ptd[0][1] = 1.68;
ptd[1][0] = 1.58;
ptd[1][1] = 1.48;
printf("the firstelement is: %f\n", ptd[0][0]);
return ptd;
}|]
let finalizer = [C.funPtr| void free2Darray(double** ptd) {
free(ptd[0]);
free(ptd);
}|]
newForeignPtr finalizer x
main = do
cArray >>= (`withForeignPtr` \e -> do
e1 <- peekElemOff e 0
e2 <- peekElemOff e1 0
print e2
)
你好,我想和 2d arrays
:
--2d arrays
cArray :: IO (Ptr (Ptr CDouble))
cArray = do
x <- [C.block| double (*)[2] {
double (*ptd)[2] = malloc(sizeof(double[2][2]));
ptd[0][0] = 1.78;
ptd[0][1] = 1.68;
ptd[1][0] = 1.58;
ptd[1][1] = 1.48;
printf("the firstelement is: %f\n", ptd[1][1]);
return ptd;
}|]
return x
然后在另一个函数中:
e <- cArray :: IO (Ptr (Ptr CDouble))
e1 <- peekElemOff e 0 :: IO (Ptr CDouble)
e2 <- peekElemOff e1 0 :: IO CDouble
print e2
这总是给出段错误。
对于一维数组,我没有问题。
有人能给我提示吗?
C 二维数组实际上只是一个一维数组,在其范围内,编译器跟踪行长度以计算二维索引。如果转换为 Ptr (Ptr CDouble)
,此大小信息将丢失。 C 二维数组不同于数组数组的二维数组——后者通常是一个 锯齿状数组,但你也可以仅通过两次分配更有效地获得这样的数组——一个对于内容,一个是指向每一行的指针。
cArray :: IO (Ptr (Ptr CDouble))
cArray = [C.block| double** {
int n = 2, m = 2;
double* arr = malloc(sizeof(double[n*m]));
double** ptd = malloc(sizeof(double*[n]));
for (int i=0; i<2; ++i)
ptd[i] = &(arr[i*m]);
ptd[0][0] = 1.78;
ptd[0][1] = 1.68;
ptd[1][0] = 1.58;
ptd[1][1] = 1.48;
printf("the firstelement is: %f\n", ptd[0][0]);
return ptd;
}|]
正如您自己所记得的,C 分配的内存最终需要再次清理。 Haskell 垃圾收集器本身无法为您完成此操作,但您可以使用 ForeignPtr
而不是原始 Ptr
.
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
import Language.C.Inline as C
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable
C.include "<stdio.h>"
C.include "<stdlib.h>"
cArray :: IO (ForeignPtr (Ptr CDouble))
cArray = do
x <- [C.block| double** {
int n = 2, m = 2;
double* arr = malloc(sizeof(double[n*m]));
double** ptd = malloc(sizeof(double*[n]));
for (int i=0; i<2; ++i)
ptd[i] = &(arr[i*m]);
ptd[0][0] = 1.78;
ptd[0][1] = 1.68;
ptd[1][0] = 1.58;
ptd[1][1] = 1.48;
printf("the firstelement is: %f\n", ptd[0][0]);
return ptd;
}|]
let finalizer = [C.funPtr| void free2Darray(double** ptd) {
free(ptd[0]);
free(ptd);
}|]
newForeignPtr finalizer x
main = do
cArray >>= (`withForeignPtr` \e -> do
e1 <- peekElemOff e 0
e2 <- peekElemOff e1 0
print e2
)