无法将 C 函数导入 Haskell
Trouble importing a C function into Haskell
我有一个调用 Haskell 函数的 C 程序。我希望 Haskell 函数负责确定数组(指针)的大小,所以我也希望 Haskell 从 C 中 malloc 指针。调用 malloc_
时出现错误在 Haskell。我不确定如何将 C malloc_((void *)&ints,sizeof(int),10);
中调用 malloc_
的方式模拟为 Haskell。
aux.c
void malloc_ (void **p, size_t size, int m) {
*p = malloc(size*m);
}
main.c
int *ints;
// want to call this function in Haskell, C doesn't know how large the array is
// malloc_((void *)&ints,sizeof(int),10);
int ints_size = setIntArray(ints);
for (int i = 0; i < ints_size; i++) {
printf("ints[%d]: %d\n", i, ints[i]);
}
Arrays.hs
#include "aux.h"
-- this might be wrong
foreign import ccall "malloc_" malloc_ :: Ptr (Ptr ()) -> CSize -> CInt -> IO ()
foreign export ccall "setIntArray" setIntArray :: Ptr CInt -> IO CInt
setIntArray :: Ptr CInt -> IO (CInt)
setIntArray is = do
let r = 10 :: Int
-- if I remove this and malloc in C then it is fine
malloc_ (castPtr is) (fromIntegral $ sizeOf is) (fromIntegral r)
x <- addArrayElement r 0
return $ fromIntegral x
where
addArrayElement :: Int -> Int -> IO Int
addArrayElement r pointerCounter =
case pointerCounter >= r of
True -> return r
False -> do
let x = 1234
poke (advancePtr is pointerCounter) (x :: CInt)
addArrayElement r (pointerCounter + 1)
忽略你的问题的其他问题,只解决关于调用的部分 malloc
:你有几个选择。
在这种情况下,malloc
已作为 malloc, or you can even use mallocArray 导入。
如果你真的想自己导入 malloc
(也许你真的想使用不同的分配器),你可以通过返回指针值来让事情变得更方便你的包装器,就像 malloc
本身一样:
void *malloc_ (size_t size, int m) {
return malloc(size*m);
}
然后foreign import ccall "malloc_" malloc_ :: CSize -> CInt -> IO (Ptr ())
,直接调用即可。
如果你真的想使用这种输出参数风格void malloc_ (void **p, size_t size, int m)
,那么你必须为一个void *
分配存储空间,这样你就可以将它的地址作为malloc_
的第一个参数,就像你在 C 中所做的那样。
my_allocated_pointer <- with nullPtr $ \pp -> do
malloc_ pp (fromIntegral $ sizeOf (undefined :: CInt)) (fromIntegral 10)
peek pp
(现在开始变得有点傻了,因为 with 在内部使用 malloc
...但这是您通常会使用的方法。)
我有一个调用 Haskell 函数的 C 程序。我希望 Haskell 函数负责确定数组(指针)的大小,所以我也希望 Haskell 从 C 中 malloc 指针。调用 malloc_
时出现错误在 Haskell。我不确定如何将 C malloc_((void *)&ints,sizeof(int),10);
中调用 malloc_
的方式模拟为 Haskell。
aux.c
void malloc_ (void **p, size_t size, int m) {
*p = malloc(size*m);
}
main.c
int *ints;
// want to call this function in Haskell, C doesn't know how large the array is
// malloc_((void *)&ints,sizeof(int),10);
int ints_size = setIntArray(ints);
for (int i = 0; i < ints_size; i++) {
printf("ints[%d]: %d\n", i, ints[i]);
}
Arrays.hs
#include "aux.h"
-- this might be wrong
foreign import ccall "malloc_" malloc_ :: Ptr (Ptr ()) -> CSize -> CInt -> IO ()
foreign export ccall "setIntArray" setIntArray :: Ptr CInt -> IO CInt
setIntArray :: Ptr CInt -> IO (CInt)
setIntArray is = do
let r = 10 :: Int
-- if I remove this and malloc in C then it is fine
malloc_ (castPtr is) (fromIntegral $ sizeOf is) (fromIntegral r)
x <- addArrayElement r 0
return $ fromIntegral x
where
addArrayElement :: Int -> Int -> IO Int
addArrayElement r pointerCounter =
case pointerCounter >= r of
True -> return r
False -> do
let x = 1234
poke (advancePtr is pointerCounter) (x :: CInt)
addArrayElement r (pointerCounter + 1)
忽略你的问题的其他问题,只解决关于调用的部分 malloc
:你有几个选择。
-
在这种情况下,
malloc
已作为 malloc, or you can even use mallocArray 导入。如果你真的想自己导入
malloc
(也许你真的想使用不同的分配器),你可以通过返回指针值来让事情变得更方便你的包装器,就像malloc
本身一样:void *malloc_ (size_t size, int m) { return malloc(size*m); }
然后
foreign import ccall "malloc_" malloc_ :: CSize -> CInt -> IO (Ptr ())
,直接调用即可。如果你真的想使用这种输出参数风格
void malloc_ (void **p, size_t size, int m)
,那么你必须为一个void *
分配存储空间,这样你就可以将它的地址作为malloc_
的第一个参数,就像你在 C 中所做的那样。my_allocated_pointer <- with nullPtr $ \pp -> do malloc_ pp (fromIntegral $ sizeOf (undefined :: CInt)) (fromIntegral 10) peek pp
(现在开始变得有点傻了,因为 with 在内部使用
malloc
...但这是您通常会使用的方法。)