I have a C function that looks something like this:
/**
* @n the outer dimension of data
* @lengths the length of each "row" of data
* @data the data itself
*/
double foo(int n, int* lengths, double** data);
I would like to call this function from Haskell, but am not sure how best to handle allocating the inner arrays of the data
pointer. In essence, I have something like this:
foreign import ccall "foo.h foo"
c_foo :: CInt -> Ptr CInt -> Ptr (Ptr CDouble) -> CDouble
haskFoo :: Int -> [Int] -> [[Double]] -> Double
haskFoo :: n lengths data = unsafePerformIO $
allocaArray n $ \lengths_ptr -> do
pokeArray lengths_ptr (map fromIntegral lengths)
allocaArray n $ \data_outer_ptrs -> do
-- TODO alloc inner arrays
x <- c_foo (fromIntegral n) lengths_ptr data_outer_ptrs
return realToFrac x
Ideally I would use something alike allocaArray
or withStorableArray
(as in the answer here), but I don't know how to do so with a runtime number of nested lambdas. I think I can accomplish what I want with mallocArray
but would prefer to use something in the style of alloca
that ensures cleanup of the allocated memory.
You don't need to allocate each array separately, just allocate one array with length sum lengths
, and then the i'th individual pointer is plusPtr arrayPtr (sum (take i lengths))
.
If for some reason you must allocate these discontiguously, just write your allocation recursively (pseudocode, may contain typos):
withRagged lengths ds h = go lengths ds [] where
go (n:lengths) (d:ds) rptrs = alloca n \d_ptr -> go lengths ds (d_ptr:rptrs)
go [] [] rptrs = h (reverse rptrs)
hasFoo lengths ds = withArray (map fromIntegral lengths) \lengths_ptr ->
withRagged lengths data \data_ptrs ->
-- ...
The n
parameter seems superfluous and probably shouldn't be part of the Haskell API (nor should, for that matter, be the list of lengths). If you want to avoid the more expensive length
, just use Vector
instead of []
.