FFI Ptr CFile problem

Christoph Flamm xtof@tbi.univie.ac.at
Fri, 22 Aug 2003 16:32:59 +0200


my problem is as follows:

I have a c-function "bla()" which gets a stream for reading ( FILE *rx ).
Within "bla()" alternating a c-function "getlineC()" and a haskell-function
"getlineHS()" should read a line from stream rx and print it.

void bla ( FILE *rx ) {
 char *line

 for ( ;; ) {
  line = getlineC( rx );
  printf ( "%s\n", line );
  free( line );

  line = getlineHs( rx );
  printf ( "%s\n", line );

How do i pass the stream FILE *rx to the haskell-function properly?

I tried to pass FILE *rx as a Ptr Cfile and converting it back into
something of type Handle in getlineHS,

module Cfile ( getLineHs ) where

import IO
import Foreign ( Ptr )
import Foreign.C.Types ( CFile, CInt )
import Foreign.C.String ( CString, newCString )
import System.Posix.IO ( fdToHandle )

foreign export ccall "getLineHs" getLineHs :: Ptr CFile -> IO (CString)
getLineHs :: Ptr CFile -> IO (CString)
getLineHs file
    = do
      hdl <- getInStream file
      hGetLine hdl >>= newCString 

foreign import ccall "stdio.h fileno" cfileno :: Ptr CFile -> IO CInt
getInStream :: Ptr CFile -> IO (Handle)
getInStream f = cfileno f >>= fdToHandle . fromIntegral

but this doesn't work (i seem to lose the file position indicator)
and i get the following error:

Fail: end of file
Action: hGetLine
Handle: {loc=<file descriptor: 3>,type=readable,
         binary=True,buffering=block (8192)}
File: <file descriptor: 3>

If i pass the file position indicator explicitly as a double value between
c and haskell and use the functions hTell/hSeek, ftell/fseek to get/set the
file position indicator the whole thing works for files but doesn't work
for pipes.

Any help would be appreciated.