passing Strings with FFI
Manuel M. T. Chakravarty
chak@cse.unsw.edu.au
Thu, 21 Jun 2001 10:59:52 +1000
"Julian Seward (Intl Vendor)" <v-julsew@microsoft.com> wrote,
> | I want to pass a String to a function which is imported from C code:
> | foreign import "pass" prim_pass :: String -> String
> | The declaration above gives me an error from ghc like "String
> | type not
> | supported for imported functions".
> | I thought that String being [Char] should be supported
> | (somehow like a
> | definition with "newtype" keyword).
> | Can you tell me how can I pass strings to and from C code, as
> | simple as
> | possible (I know about HDirect, but I couldn't make it work
> | for me: red-hat
> | 7.1, ghc 5.00)?
>
> First of all, upgrade to 5.00.2, since it is significantly less
> buggy than 5.00.
>
>
> int fooble ( char* str, int n )
> {
> fprintf(stderr, "fooble called: %s %d\n", str, n );
> return 42;
> }
>
>
> import PrelByteArr
> import PrelPack (packString)
>
> foreign import "fooble" fooble
> fooble :: PackedString -> Int -> IO Int
>
> type PackedString = ByteArray Int
>
> main = do n <- fooble (packString "hello, C world") 99
> putStrLn ("Returned value is " ++ show n)
>
> For more examples read the compiler sources, at
> fptools/ghc/compiler/ghci/Linker.lhs.
Actually, the portable way of achieving the same effect with
the new FFI libraries is
import Foreign
import CForeign
foreign import fooble :: CString -> Int -> IO Int
main = withCStringLen "hello, C world" $ \(strPtr, strLen) -> do
n <- fooble strPtr strLen
putStrLn ("Returned value is " ++ show n)
Note that it is not really necessary to pass the length
information explicitly. The CString will be NUL terminated
and so directly usable by C. I just wanted to exactly
imitate the cited example. If you don't need the string
length, the simpler function `withCString' is sufficient.
To marshall a string from C to Haskell land, use the
function `CForeign.peekCString'.
See
http://haskell.cs.yale.edu/ghc/docs/latest/set/sec-foreign.html
http://haskell.cs.yale.edu/ghc/docs/latest/set/sec-cforeign.html
for details.
The principal advantage of using Foreign and CForeign
instead of the Prel* functions is that the former are part
of the Haskell FFI standard that we are working at and so,
for example, are also supported by NHC.
Cheers,
Manuel