4
votes

I'm in the process of working on haskell bindings for a native library with a pretty complex interface. It has a lot of structs as part of its interface, and I've been working on building interfaces to them with hsc2hs and the bindings-DSL package for helping automate struct bindings.

One problem I've run into, though, is with structs that contain multidimensional arrays. The bindings-DSL documentation describes macros for binding to a structure like

struct with_array {
   char v[5];
   struct test *array_pointer;
   struct test proper_array[10];
};

with macros like

#starttype struct with_array
#array_field v , CChar
#field array_pointer , Ptr <test>
#array_field proper_array , <test>
#stoptype

But this library has many structs with multidimensional arrays as fields, more like

struct with_multidimensional_array {
   int whatever;
   struct something big_array[10][25][500];
};

The #array_field macro seems to only handle the first dimension of the array. Is it the case that bindings-DSL just doesn't have a macro for handling multidimensional arrays?

I'd really like a macro for binding a (possibly-multidimensional) array to a StorableArray of arbitrary indexes. Seems like the necessary information is possible in the macros bindings-DSL provides - there's just no macro for this.

Has anyone added macros to bindings-DSL? Has anyone added a macro for this to bindings-DSL? Am I way past what I should be doing with hsc2hs, and there's some other tool that would help me do what I want in a more succinct way?

2
I guess I could create a newtype wrapping StorableArray with a Storable instance specifically for that field, and just use the #field macro. This seems sane, in the absence of any better solution.Carl

2 Answers

1
votes

Well, no one's come up with anything else, so I'll go with the idea in my comment. I'll use the #field macro instead of the #array_field macro, and specify a type that wraps StorableArray to work correctly.

Since I was thinking about this quite a bit, I realized that it was possible to abstract out the wrapper entirely, using the new type-level numbers that GHC 7.6+ support. I put together a package called storable-static-array that takes dimensions on the type level and provides a proper Storable instance for working with native arrays, even multidimensional ones.

One thing that's still missing, that I would like greatly, is to find a way to write a bindings-DSL compatible macro that automatically extracts dimensions and takes care of generating them properly. A short glance at the macros in bindings-DSL, though, convinced me that I don't know nearly enough to manage it myself.

1
votes

The #array_field macro handles arrays with any dimension. Documentation has been updated to show that explicitly.

The Haskell equivalent record will be a list. When peeking and poking, the length and order of the elements of that list will correspond to the array as it were considered as a one-dimensional array in C. So, a field int example[2][3] would correspond to a list with 6 elements ordered as example[0][0], example[0][1], example[0][2], example[1][0], example[1][1], example[1][2]. When poking, if the list has more than 6 elements, only the first 6 would be used.

This design was choosen for consistency with peekArray and pokeArray from FFI standard library. Before version 1.0.17 of bindings-DSL there was a bug that caused the size of that list to be underestimated when array fields had dimension bigger than 1.