Library/libffi

From HaskellWiki
< Library
Revision as of 19:38, 4 June 2009 by Remi (talk | contribs) (create libffi "homepage")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

libffi is a binding to the C library libffi, allowing C functions to be called whose types are not known before run-time.

It was designed to easily enable the addition of an foreign function interface to a (not-yet-released) new interpreter.

How to use it

The main function it exports is:

 callFFI :: FunPtr a -> RetType b -> [Arg] -> IO b

In addition, many values like retWord64 :: RetType Word64 and argCULong :: CULong -> Arg are exported.

The main module to import is Foreign.LibFFI. Importing the other modules should only be necessary when one wants to extend the API to support passing/returning new types to C.

Example

And because code is worth a thousand words, here a small program that uses C calls to write a 1Gb buffer of uninitialized garbage to a file:

import System.Posix.DynamicLinker
import Foreign.LibFFI
main = do
    malloc <- dlsym Default "malloc"
    creat  <- dlsym Default "creat"
    write  <- dlsym Default "write"
    let sz = 2 ^ 30
    buf <- callFFI malloc (retPtr retVoid) [argCSize sz]
    fd  <- callFFI creat  retCInt          [argString "/tmp/test", argCUInt 0o644]
    n   <- callFFI write  retCSize         [argCInt fd, argPtr buf, argCSize sz]
    putStrLn $ show n ++ " bytes written"

More interesting examples are included in examples/ in the package.

Does it work?

It should work on any 32/64bits machine on which libffi works, but has been primarily tested on linux x86_64. The current libffi is not exception-safe (exception = memory leak) and callFFI has quite some overhead that would be unnecessary with another api. It is, however, very easy to use.

In the long term, I am not sure whether it will survive in its current form: Although easy, the current API makes it impossible to be really efficient (with the lists, decoding and initialization for each call). In addition, libffi doesn't work on windows, and I am not sure whether e.g. a C/Invoke binding would use the same API.

How to get and install it

A cabal package is available here.

If you have cabal-install installed, this should also work:

cabal install libffi