[ANNOUNCE] Bindings for libguestfs

I added some partial bindings for libguestfs[1] here: http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=haskell/Guestfs.hs;hb=HE... Some very simple example programs which use these bindings: http://git.et.redhat.com/?p=libguestfs.git;a=tree;f=haskell;hb=HEAD Any comments welcome. My Haskell skills are pretty terrible, so I'm sure there are many ways these can be improved. If someone wants to look at binding the rest of the API, then please send me some patches. (Note that the Guestfs.hs file is automatically generated). BTW, I found the documentation on writing FFIs very contradictory and incomplete. For example, I was completely defeated trying to find ways to do simple stuff like passing in integers or returning booleans. *Potentially* Haskell's FFI seems like it might be one of the best out of the languages I've used so far, but it needs way more documentation and examples. Rich. [1] http://et.redhat.com/~rjones/libguestfs/ -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/

rjones:
I added some partial bindings for libguestfs[1] here:
http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=haskell/Guestfs.hs;hb=HE...
Some very simple example programs which use these bindings:
http://git.et.redhat.com/?p=libguestfs.git;a=tree;f=haskell;hb=HEAD
Any comments welcome. My Haskell skills are pretty terrible, so I'm sure there are many ways these can be improved.
If someone wants to look at binding the rest of the API, then please send me some patches. (Note that the Guestfs.hs file is automatically generated).
Very cool. Are you likely to upload to hackage?
BTW, I found the documentation on writing FFIs very contradictory and incomplete. For example, I was completely defeated trying to find ways to do simple stuff like passing in integers or returning booleans. *Potentially* Haskell's FFI seems like it might be one of the best out of the languages I've used so far, but it needs way more documentation and examples.
Perhaps read the FFI chapter of RWH (online?) What resources were you using to grok the FFI? Cheers, Don

On Tue, May 12, 2009 at 08:18:08AM -0700, Don Stewart wrote:
rjones:
I added some partial bindings for libguestfs[1] here:
http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=haskell/Guestfs.hs;hb=HE...
Some very simple example programs which use these bindings:
http://git.et.redhat.com/?p=libguestfs.git;a=tree;f=haskell;hb=HEAD
Any comments welcome. My Haskell skills are pretty terrible, so I'm sure there are many ways these can be improved.
If someone wants to look at binding the rest of the API, then please send me some patches. (Note that the Guestfs.hs file is automatically generated).
Very cool. Are you likely to upload to hackage?
I think it should be a bit more complete before uploading it. It only covers about half the interface.
BTW, I found the documentation on writing FFIs very contradictory and incomplete. For example, I was completely defeated trying to find ways to do simple stuff like passing in integers or returning booleans. *Potentially* Haskell's FFI seems like it might be one of the best out of the languages I've used so far, but it needs way more documentation and examples.
Perhaps read the FFI chapter of RWH (online?)
What resources were you using to grok the FFI?
Well, Real World Haskell was one of the resources: http://book.realworldhaskell.org/read/interfacing-with-c-the-ffi.html (And it's fine, one of the better resources as an introduction. But not thorough enough to cover the booleans / returning complex structs problems I had). The others, as I remember it, were: http://www.haskell.org/haskellwiki/FFI_Introduction http://www.haskell.org/haskellwiki/FFICookBook (Made me think it was simple, but doesn't really cover much once I got down to the details) http://www.cse.unsw.edu.au/~chak/haskell/ffi/ & the documentation for 'Foreign' etc in the Haddock-generated library docs. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/

rjones:
On Tue, May 12, 2009 at 08:18:08AM -0700, Don Stewart wrote:
rjones:
I added some partial bindings for libguestfs[1] here:
http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=haskell/Guestfs.hs;hb=HE...
Some very simple example programs which use these bindings:
http://git.et.redhat.com/?p=libguestfs.git;a=tree;f=haskell;hb=HEAD
Any comments welcome. My Haskell skills are pretty terrible, so I'm sure there are many ways these can be improved.
If someone wants to look at binding the rest of the API, then please send me some patches. (Note that the Guestfs.hs file is automatically generated).
Very cool. Are you likely to upload to hackage?
I think it should be a bit more complete before uploading it. It only covers about half the interface.
BTW, I found the documentation on writing FFIs very contradictory and incomplete. For example, I was completely defeated trying to find ways to do simple stuff like passing in integers or returning booleans. *Potentially* Haskell's FFI seems like it might be one of the best out of the languages I've used so far, but it needs way more documentation and examples.
Perhaps read the FFI chapter of RWH (online?)
What resources were you using to grok the FFI?
Well, Real World Haskell was one of the resources:
http://book.realworldhaskell.org/read/interfacing-with-c-the-ffi.html
(And it's fine, one of the better resources as an introduction. But not thorough enough to cover the booleans / returning complex structs problems I had).
The others, as I remember it, were:
http://www.haskell.org/haskellwiki/FFI_Introduction http://www.haskell.org/haskellwiki/FFICookBook
(Made me think it was simple, but doesn't really cover much once I got down to the details)
http://www.cse.unsw.edu.au/~chak/haskell/ffi/
& the documentation for 'Foreign' etc in the Haddock-generated library docs.
Very good. I wonder if /you/ could note down (maybe on the wiki) the things you need to work out - then we would have a tutorial from someone learning on the job. That could then be fleshed out into a fuller tutorial? -- Donn

Richard,
I added some partial bindings for libguestfs[1] here: http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=haskell/Guestfs.hs;hb=HE...
Terrific! Partial bindings are great. Thanks for releasing it. I haven't taken the time to look at your code, but...
BTW, I found the documentation on writing FFIs very contradictory and incomplete. For example, I was completely defeated trying to find ways to do simple stuff like passing in integers or returning booleans. *Potentially* Haskell's FFI seems like it might be one of the best out of the languages I've used so far, but it needs way more documentation and examples.
Can you be more specific about what needs improvement? I wrote a partial Haskell binding for Net-SNMP recently, and I got along pretty well using the API docs at http://www.haskell.org/ghc/docs/latest/html/libraries/index.html, and an example in RWH using hsc2hs. What did you see that was contradictory? Regards, John

On Tue, May 12, 2009 at 03:11:32PM -0400, John Dorsey wrote:
Richard,
I added some partial bindings for libguestfs[1] here: http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=haskell/Guestfs.hs;hb=HE...
Terrific! Partial bindings are great. Thanks for releasing it. I haven't taken the time to look at your code, but...
BTW, I found the documentation on writing FFIs very contradictory and incomplete. For example, I was completely defeated trying to find ways to do simple stuff like passing in integers or returning booleans. *Potentially* Haskell's FFI seems like it might be one of the best out of the languages I've used so far, but it needs way more documentation and examples.
Can you be more specific about what needs improvement?
I wrote a partial Haskell binding for Net-SNMP recently, and I got along pretty well using the API docs at http://www.haskell.org/ghc/docs/latest/html/libraries/index.html, and an example in RWH using hsc2hs.
I guess it's easier if one is more used to Haskell (see my .sig)
What did you see that was contradictory?
Specific things would be: Recommendation to use 'throwDyn' to throw exceptions, yet this function doesn't exist in my version of GHC. In fact, none of the code here: http://www.haskell.org/haskellwiki/FFICookBook#Raising_and_handling_exceptio... works in GHC at all, as far as I could tell. No good examples available on how to use ForeignPtr. Yet I'd argue that almost any non-trivial modern C library bindings will have some concept of an opaque object, so this is the most vital example. (The examples in RWH ch 17 weren't enough for me). I'd really like to know what parameters and return types are permissible for 'foreign import ccall' statements. By trial and error I found out. How do I convert to/from booleans? How do I really use C structures? Real examples, please. How can I free a C string that is returned from a 'caller frees' C function? Does Foreign.Marshall.Alloc.free work for this? Again, reflecting my own inexperience with Haskell, I found 'withCString', 'maybeWith', 'withMany', 'withArray0' etc to be both undocumented and extremely confusing to use. How do I specify a 64 bit int? Using 'Int64#' just causes syntax errors. What's a good emacs editing mode for Haskell code? My emacs thinks Haskell code is LISP ... Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 75 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora

Richard, I remember having similar problems to you when trying to use the FFI. The following comments are suggestions as to what helps in practice, and not a claim that the situation can't be improved. On 13/05/2009, at 8:40 PM, Richard W.M. Jones wrote:
Specific things would be:
Recommendation to use 'throwDyn' to throw exceptions, yet this function doesn't exist in my version of GHC. In fact, none of the code here:
http://www.haskell.org/haskellwiki/FFICookBook#Raising_and_handling_exceptio...
works in GHC at all, as far as I could tell.
The shifting exceptions story is a PITA. Compatibility is the price of progress.
No good examples available on how to use ForeignPtr. Yet I'd argue that almost any non-trivial modern C library bindings will have some concept of an opaque object, so this is the most vital example. (The examples in RWH ch 17 weren't enough for me).
I'd suggest you download a mature library binding close to what you want to do and ape that. For example: 1. got lots of C structures? look at a GTK binding. 2. got a fairly imperative API? look at a database binding, or HOpenGL. 3. got a fairly pure API? look at a BDD or numerical package binding. and so forth. The FFI itself is intended to be minimal, just enough to do the job. The idea was that extra tools (most prominently hsc2hs and c2hs, historically greencard) would support large bindings. It's funny you say "opaque object". ForeignPtr only handles pointers. In one library I relied on, the opaque objects were represented with ints. It'd be nice to track arbitrary values the way that ForeignPtr tracks C pointers.
I'd really like to know what parameters and return types are permissible for 'foreign import ccall' statements. By trial and error I found out.
Is the FFI spec unclear on this point?
How do I convert to/from booleans?
Can you use the methods of the Enum class?
How do I really use C structures? Real examples, please.
I'd suggest looking into c2hs. Even if you don't use it, the code it generates is quite illuminating, especially how it pushes values between C and Haskell.
How can I free a C string that is returned from a 'caller frees' C function? Does Foreign.Marshall.Alloc.free work for this?
This is tricky. Rather than give you a definite answer, I'd suggest you check with the FFI spec. IIRC in principle the FFI's malloc/free could be distinct from those in C land, but in practice (GHC) they coincide.
Again, reflecting my own inexperience with Haskell, I found 'withCString', 'maybeWith', 'withMany', 'withArray0' etc to be both undocumented and extremely confusing to use.
They're documented in the FFI spec. Granted using them is not necessarily intuitive, which is where looking at existing code might help.
How do I specify a 64 bit int? Using 'Int64#' just causes syntax errors.
Did you look into the Data.Word library?
What's a good emacs editing mode for Haskell code? My emacs thinks Haskell code is LISP ...
There's been a Haskell mode for at least a decade now. It's packaged with every emacs I've used in the past few years. http://www.haskell.org/haskell-mode/ To editorialise a bit, I think the original FFI spec is very clearly written, and the contradictions you allude to lie in fact in the more recent wiki writeups; the Haskell specs are lucid and intended to be usable, and not just by the compiler writers. One last gotcha: be very careful about strictness if you're trying to graft a pure API onto the library. Hope this helps! cheers peter

On Wed, May 13, 2009 at 11:15:24PM +1000, Peter Gammie wrote:
Hope this helps!
Thanks for your honest & helpful answer. I think I will try again at compiling c2hs so I can look at the code that it generates. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/
participants (4)
-
Don Stewart
-
John Dorsey
-
Peter Gammie
-
Richard W.M. Jones