Marshall Multidimensional list, multidimensional array

Dear all, I have a data of type[[Int]] format, how can I marshal it to int[][] in C using withArray or newArray command ? Some help please. Thank you for your attention and help. Best Regards, David

David Lo writes:
[[Int]] to int[][]
Pardon me if I'm telling you something you already know, but I wanted to make sure you are aware of it. int[][] is a very different type than [[Int]] is. An int[][] is a pointer to an array of pointers to integers: int[][] <==> int*[] <==> int** Now think of the following Haskell list: [ [ 1, 2, 3, 4] , [ 1 ] , [ 1, 2 ] ] C can't easily express that because an array in C does not have a length -- a list in Haskell, however, does. To understand the difference, just ask yourself what the element my_list[1][3] would be. In the Haskell type, this element does not exist: The second list has only one element. Only, C doesn't know that! It will simply translate the expression to: *( *(my_list + 1) + 3 ) And give you the contents of any random memory location, thus, almost certainly crashing your program. Which is why C sucks and Haskell rules. :-) My point is: marshaling a nested list is really not as simple as it looks and int[][] is almost certainly not the right type to marshal to. You'd need something that contains the information which element list is how long, something like: struct integer_list { size_t len; int* elements; } struct nested_list { size_t len; integer_list* elements } What _exactly_ you would need, though, is impossible to say without understanding what you are trying to do. And explaining all this would probably be too complex to do it casually on a public mailing list. I hope this helps somewhat. And I hope I remembered the order in which C does resolve the int[][] type correctly. I could never get that right. I hope someone corrects me, should it be wrong. Peter

Peter Simons wrote:
[[Int]] to int[][]
Pardon me if I'm telling you something you already know, but I wanted to make sure you are aware of it.
int[][] is a very different type than [[Int]] is. An int[][] is a pointer to an array of pointers to integers:
No it isn't; it's an array of arrays of integers. As C passes arrays
by reference rather than value, it will be passed as a pointer to
arrays of integers.
However, you can't use "int[][]" directly as a type; all dimensions
other than the first must be specified. E.g. "int [][4]" is an array
of arrays-of-length-4 of integers, and will be passed as a pointer to
arrays-of-length-4 of integers (i.e. incrementing the pointer will
increment by 4*sizeof(int) bytes).
Consequently, you can't directly use withArray, as that only works on
lists whose elements are members of the Storable class, and lists
aren't themselves members of Storable.
To marshall such a list, one approach would be to simply flatten the
list with concat, i.e.:
withArray2D :: (Storable a) => [[a]] -> (Ptr a -> IO b) -> IO b
withArray2D xs f = withArray (concat xs) f
So long as all of the sublists are of the same length, this will do
the right thing. If the sublists are of differing length, you would
first need to either truncate or pad them to the same length, e.g.:
withArray2D :: (Storable a) => [[a]] -> (Ptr a -> IO b) -> IO b
withArray2D xs f = withArray xs' f
where xs' = concat $ map (take dim) xs
dim = minimum $ map length xs
Padding is slightly more complex, as you have to choose a value with
which to pad.
--
Glynn Clements

glynn@gclements.plus.com writes:
To marshall a [[Int]] ...
withArray2D xs f = withArray (concat xs) f
withArray2D xs f = withArray xs' f where xs' = concat $ map (take dim) xs dim = minimum $ map length xs
Um, I really wouldn't use the term "marshaling" when talking about these functions because in the general case the result of the first one will crash your process and the second one loses data. Peter
participants (3)
-
David Lo
-
glynn@gclements.plus.com
-
Peter Simons