Hi, I'd like to call LaPack routines from Haskell. Having read the GreenCard documentation it's still not obvious to me how I could marshall a list of numbers to C. Surely it's possible to create a ForeignObj, then fill it in element-by- element. But isn't there a more straightforward way? Even without monads? Cheers: Feri.
Well, you could just use Ptr Double to mimick c arrays and define conversion functions. I'm currently porting BLAS and LAPACK to Haskell and this is what I do. -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Mon, 3 Jun 2002, Ferenc Wagner wrote:
Hi,
I'd like to call LaPack routines from Haskell. Having read the GreenCard documentation it's still not obvious to me how I could marshall a list of numbers to C. Surely it's possible to create a ForeignObj, then fill it in element-by- element. But isn't there a more straightforward way? Even without monads?
Cheers: Feri. _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Hal Daume III <hdaume@ISI.EDU> writes:
Well, you could just use Ptr Double to mimick c arrays and define conversion functions. I'm currently porting BLAS and LAPACK to Haskell and this is what I do.
Great! Can you show me what you have done so far? It is urgent for me, but I need one singe routine (sspev). If you haven't ported this yet, I'll try to do so. Feri.
Hi, I'd like to call LaPack routines from Haskell. Having read the GreenCard documentation it's still not obvious to me how I could marshall a list of numbers to C. Surely it's possible to create a ForeignObj, then fill it in element-by- element. But isn't there a more straightforward way? Even without monads?
Here's some code from the Xlib interface: hslibs/xlib/Xlib.gc (This code is part of the HGL (http://haskell.org/graphics).) First, a function that wants a list of objects. Note that we use ListPoint (a type synonym we'll define below) instead of [Point]. The name 'ListPoint' triggers the appropriate kind of marshalling. Note too that the %call line contains: (listPoint arg4 arg4_size) That is, listPoint marshalling results in 2 arguments to the C function.
%fun XDrawPoints :: Display -> Drawable -> GC -> ListPoint -> CoordinateMode -> IO () %call (display arg1) (drawable arg2) (gC arg3) (listPoint arg4 arg4_size) (coordinateMode arg5) %code XDrawPoints(arg1,arg2,arg3,arg4,arg4_size,arg5) %end free(arg4)
Marshalling lists of points uses the functions marshallAddrList and unmarshallAddrList (defined later).
type ListPoint = [Point] %dis listPoint x l = <<marshallAddrList allocPoints writePoint/unmarshallAddrList readPoint>> (addr ({XPoint*} x)) (int l)
To marshall a list of points we have to allocate some space in the C heap. Note that the size is scaled by the size of the objects.
%fun allocPoints :: Int -> IO Addr %code res1 = (void*)malloc(sizeof(XPoint) * arg1)
write points into an array
%fun writePoint :: Addr -> Int -> Point -> IO () %call (addr ({XPoint*} s)) (int i) (point {s[i]}) %code
and read points from an array
%fun readPoint :: Addr -> Int -> IO Point %call (addr ({XPoint*} s)) (int i) %code %result (point {s[i]})
These functions are useful with many different types of list. To marshall we: 1) Get the list length 2) Allocate an array that size in the C heap 3) Write values into the array.
marshallAddrList :: (Int -> IO Addr) -> (Addr -> Int -> a -> IO ()) -> [a] -> IO (Addr, Int) marshallAddrList alloc write as = do let l = length as arr <- alloc l zipWithM_ (write arr) [0..] as return (arr, l)
To unmarshall we read values out. Freeing the array could be done here too but in this case it happens in the %end of the %fun that uses the array. It's a long time since I wrote this code so I can only guess that I thought this way would be more flexible.
unmarshallAddrList :: (Addr -> Int -> IO a) -> (Addr, Int) -> IO [a] unmarshallAddrList read (ptr,l) = mapM (read ptr) [0..l-1]
Points are defined in the usual way. I won't discuss this much since I think you just want Int or Floats or some such.
type Point = ( Position -- x , Position -- y )
%dis point x = declare {XPoint} x in % ( position {(%x).x} % , position {(%x).y} % )
Hope this helps, -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
Alastair Reid <reid@cs.utah.edu> writes:
Here's some code from the Xlib interface: hslibs/xlib/Xlib.gc (This code is part of the HGL (http://haskell.org/graphics).)
[...]
Hope this helps,
It helped much. Thanks for the comments, especially. Now I'm going to check whether the garbage collector works: both the Haskell and the C representation won't fit in memory... Thanks again! Feri.
wferi@afavant.elte.hu writes:
Now I'm going to check whether the garbage collector works: both the Haskell and the C representation won't fit in memory...
If you're using a foreign library to process very large datasets (e.g., image processing, large matrix operations, etc.) it's usual to keep the data on the C side and never transfer the whole dataset into Haskell at the one time. If you want to do this, you'd change an interface like this: type Matrix a = [[a]] -- or any other Haskell representation %dis invert :: Matrix Double -> Matrix Double %dis add :: Matrix Double -> Matrix Double -> Matrix Double ... instance Show a => Show (Matrix a) where ... to one like this: data CMatrix a -- declares a type but no representation type Matrix a = ForeignPtr (CMatrix a) %dis invert :: Matrix Double -> Matrix Double %dis add :: Matrix Double -> Matrix Double -> Matrix Double ... %dis printMatrix :: Matrix Double -> IO () That is, we change the representation to use a ForeignPtr (a pointer into the C heap) and we try to replace functions which access the representation directly with C functions. -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
participants (3)
-
Alastair Reid -
Ferenc Wagner -
Hal Daume III