Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use Haskell's FFI on structs?

I have created the following C library for reading an image:

typedef struct {
    unsigned int height;
    unsigned int width;

    unsigned char* red; //length=height*width
    unsigned char* green;
    unsigned char* blue;
} Contents;

Contents readJPEGFile(const char* inFilename);

I can't really find any info using arrays and structs with the Foreign Function Interface. How would I proceed to be able to use my library in Haskell?

I tried to use the following example as a base: http://therning.org/magnus/archives/315 but then the hsc file was compiled down to a hs file that only contained the above c-code and nothing more (and of course it can't be compiled).

like image 931
Daniel O Avatar asked Mar 21 '09 23:03

Daniel O


2 Answers

The basic FFI support includes only scalar types. Everything else you wind up doing with address arithmetic. The section on foreign types in the FFI documentation gives the basics, and you can find an example in the FFI Cookbook.

At one time you could use tools like Green Card and H/Direct to generate marshalling and unmarshalling code for you. For reasons I don't understand, these tools have not been updated in a long time. As far as I can tell the current tool of choice is hsc2hs.


Edit: As noted in comment (thanks ephemient), c2hs is also popular, and since c2hs is from Manuel Chakravarty it is likely to be good.

like image 99
Norman Ramsey Avatar answered Oct 16 '22 09:10

Norman Ramsey


It sounds as if you have a build issue; I do seem to recall that I used the very page you reference as an example when I was writing an FFI interface into the Windows Win32 DDEML library. For example, one of the structures we use is

typedef struct tagHSZPAIR {
    HSZ     hszSvc;
    HSZ     hszTopic;
} HSZPAIR, *PHSZPAIR;

#include "ddeml.h" brings this in to the DDEML.hsc file. We access it with:

data HSZPair = HSZPair HSZ HSZ
instance Storable HSZPair where
    sizeOf _                     = (#size HSZPAIR)
    alignment                    = sizeOf
    peek ptr                     = do svc   <- (#peek HSZPAIR, hszSvc)   ptr
                                      topic <- (#peek HSZPAIR, hszTopic) ptr
                                      return $ HSZPair svc topic
    poke ptr (HSZPair svc topic) = do (#poke HSZPAIR, hszSvc)   ptr svc
                                      (#poke HSZPAIR, hszTopic) ptr topic

Unfortunately, I can't show you what this compiles to at the moment because I don't have a Windows box handy, but the generated code was just as above, except with #size HSZPAIR replaced with (64) or whatever and so on.

(If you really want to see what was generated, or need help doing your build, e-mail me and I'll help you out.)

like image 30
cjs Avatar answered Oct 16 '22 09:10

cjs