Next Previous Contents

3.1 Calling C from Haskell

Suppose we want to be able to call the POSIX directory manipulating functions from Haskell, which has the following C function prototypes:

DIR* opendir(const char* dirname);
struct dirent* readdir(DIR* dirp);
int closedir(DIR* dirp);
void rewinddir(DIR* dirp);

To do this with H/Direct, you'll first have to convert the above C function prototypes into IDL:

module Dir {

// DIR is an abstract type, so we represent DIR* as an
// abstract type here.
interface DIRPtr {};

// POSIX mandates that (struct dirent) just has a member called
// d_name, so we cannot portably define the struct in IDL.
// (the programmer will have to supply a C stub, getEntryName,
// to fish out the name instead). So, we define the directory
// entry type to be abstract too.
interface direntPtr {};

DIRPtr opendir([in,string]char* dirname);
direntPtr readdir([in]DIRPtr dirp);
bool closedir([in]DIRPtr dirp);
void rewinddir([in]DIRPtr dirp); 

void getEntryName([in]direntPtr dp,[out,nofree,string]char** pnm);
};

The signatures are all contained within a module declaration, which simply instructs the IDL compiler to emit the Haskell stubs into the file Dir.hs. Due to the abstract definition of the DIR and struct dirent types by POSIX, we don't define them either, but represent pointers to either type by generic pointers. Things to note about the function signatures:

To generate Haskell stubs for the above functions, invoke the IDL compiler giving the spec as input:

foo% ihc -c dir.idl
Writing Dir.hs.....done
foo% 

The generated Haskell file Dir.hs contains stubs that take care invoking the directory functions, and they have the following Haskell type signatures:

newtype DIRPtr = ... --abstract
type DirentPtr = ... --abstract

opendir :: String -> IO DIRPtr
readdir :: DIRPtr -> IO DirentPtr
closedir :: DIRPtr -> IO Bool
rewinddir :: DIRPtr -> IO ()

getEntryName :: DirentPtr -> IO String

Figure H/Direct overview

See the H/Direct user's manual for more examples of how the IDL compiler can be used to generate Haskell bindings to external libraries.

Calling C from Haskell with H/Direct


Next Previous Contents