With heartfelt thanks to the many people who have already tried hs-bindgen and
given us feedback, we have steadily been working towards the first official
release (see Contributors for the full list). In case you missed
the announcement of the first alpha, hs-bindgen is a
tool for automatic construction of Haskell bindings for C libraries: just point
it at a C header and let it handle the rest. Because we have fixed some critical
bugs in this alpha release, but we’re not quite ready yet for the first full
official release, we have tagged a second alpha release. In the
remainder of this blog post we will briefly highlight the most important
changes; please refer to the CHANGELOG.md of
hs-bindgen and of
hs-bindgen-runtime for the full list of changes, as well as
for migration hints where we have introduced some minor backwards incompatible
changes.
Bugfixes
The most important fixes for bugs in the generated code are:
- The implementation of
peekandpokefor bitfields was broken, which could lead to segfaults. - Duplicate record fields are now usable also in Template Haskell mode.
- Patterns for unsigned enums now get the right value.
We have also resolved a number of panics during code generation, but those would not have resulted in incorrect generated code (merely in no code being generated at all).
New features
Implicit fields arise when one struct (or union) is nested in another, without any field name or tag:
struct outer { int x; struct { int y; int z; }; };We now support such implicit fields; both the inner (anonymous) struct as well as the corresponding field of the outer struct will be named after the first field of the inner struct1:
data Outer = Outer { x :: CInt , y :: Outer_y } data Outer_y = Outer_y { y :: CInt , z :: CInt }For this particular case we could also have chosen to flatten the structure and add
yandzdirectly toOuter, but that does not work in all cases (for example, when we have an anonymous struct inside a union), so instead we opt for consistency and always generate an explicit type for the inner struct.Unnamed bit-field declarations, which are used to control padding, are now supported:
struct bar { signed char x : 3; signed char : 3; // Explicit padding signed char y : 2; };We used to distinguish between parse predicates (which files should
hs-bindgenparse at all?) and selection predicates (for which C declarations should we generate Haskell declarations?). This was confusing, and as we are getting better at skipping over declarations with unsupported features (and that list is dwinding anyway), parse predicates are not that useful anymore. Parse predicates therefore have been removed entirely; we simply always parse everything (selection predicates are still very much an important feature of course).Some infrastructure for and around binding specifications has been improved. For example, we now distinguish between macros and non-macros of the same name, and our treatment of arrays has changed slightly. For example, given
typedef char T []; void foo (T xs);we now generate
foo :: Ptr (Elem T) -> IO ()We do not use
Ptr CChar, becauseTmight have an existing binding in another library (with an external binding specification), and we don’t know what the type of the elements ofTare (it could for example be some newtype aroundCChar).Elemis a member of a newIsArrayclass, part of thehs-bindgen-runtime.Top-level anonymous enums are now supported. For example,
enum {A, B};results in
pattern A :: CUInt pattern A = 0 pattern B :: CUInt pattern B = 1(Normally an
enumresults in anewtypearound the enum’s underlying type, and the patterns are for thatnewtypeinstead.)We now generate bindings for static global variables (such globals are sometimes used in headers that also contain static function bodies).
All definitions required by the generated code are now (re-)exported from
hs-bindgen-runtime, so that it becomes the only package dependency that needs to be declared (no need forghc-primorprimitiveanymore).
This list is not complete; some other less common edge cases have also been implemented.
Conclusions
Although we are still working on some finishing touches before we can release
the first official version of hs-bindgen, it is already being put to good use
on various projects. There are only a handful of missing C
features left, all of which low priority edge cases (though
if you have a specific use case for any of these, do let us know!). So if you
are interested, please do try it out, and let us know if you find any problems.
There should be no major breaking changes between now and the first official
release.
This is the version that uses the
--omit-field-prefixesoption, which generates code that relies onDuplicateRecordFieldsandOverloadedRecordDot.↩︎