All I want to do is pass a plain-text string from Haskell to C. However, it says that [Char] is an unacceptable return type. I can't find anywhere why they think it is, nor what acceptable return types are.
I'm trying to make a very simple OS image that I can boot with Qemu.
Does anyone know how to do this? Thanks.
{-# LANGUAGE ForeignFunctionInterface #-}
module Hello where
import Foreign
import Foreign.C.String
import Foreign.C.Types
hello :: String -> (CString -> IO a) -> IO a
hello = "Hello, world!"
foreign export ccall hello :: String -> (CString -> IO a) -> IO a
You want a
CString
.Going from
CString
toString
:Going from
String
toCString
:There's also Haddock documentation for module
Foreign.C.String
.The general list of types that can be used in
foreign
declarations is specified as part of the Foreign Function Interface in the Haskell Report.Edit
Ok, here's a very small example of a thing you can do, somewhat based on your sample code. Create a Haskell file
CTest.hs
with the following contents:Then create a C file
ctest.c
with the following contents:Then compile and run as follows:
I think what you need is
System.IO.Unsafe.unsafePerformIO
to convert IO CString to CString before sending the CString to C. newCString will convert a Haskell String to IO CString. ThusSystem.IO.Unsafe.unsafePerformIO $ newCString a
can be passed to your C routine which will accept input of typechar*
. If your C routine returns staticchar*
thenSystem.IO.Unsafe.unsafePerformIO $ peekCString
will give you back a Haskell string. You need to importSystem.IO.Unsafe
.unsafePerformIO
has an implementation inForeign.C.String
(orForeign.C.Types
?) which is deprecated, so you have to use the full path. I had a hell of a time before I could findunsafePerformIO
- probably because people are allergic to something that is so dangerous as to force declaration of impure to pure.newCString
can lead to memory leaks if used repeatedly without cleaning.withCString
may be a better option - will learn that later.