我想要做的就是将一个纯文本字符串从Haskell传递给C.但是,它说[Char]是一种不可接受的返回类型。我无法找到他们认为的原因,也无法找到可接受的返回类型。
我正在尝试制作一个非常简单的操作系统映像,我可以用Qemu启动它。
有谁知道怎么做?感谢。
{-# 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
答案 0 :(得分:14)
您需要CString
。
从CString
转到String
:
peekCString :: CString -> IO String
从String
转到CString
:
withCString :: String -> (CString -> IO a) -> IO a
还有module Foreign.C.String
的Haddock文档。
可以在foreign
声明中使用的一般类型列表被指定为Foreign Function Interface in the Haskell Report的一部分。
好的,这是一个很小的例子,你可以做一些事情,有些基于你的示例代码。使用以下内容创建Haskell文件CTest.hs
:
module CTest where
import Foreign.C
hello :: IO CString
hello = newCString "hello"
foreign export ccall hello :: IO CString
然后使用以下内容创建一个C文件ctest.c
:
#include <stdio.h>
#include "CTest_stub.h"
int main (int argc, char *argv[]) {
hs_init(&argc, &argv);
printf("%s\n", hello());
hs_exit();
return 0;
}
然后编译并运行如下:
$ ghc CTest
[1 of 1] Compiling CTest ( CTest.hs, CTest.o )
$ ghc -o ctest ctest.c CTest.o -no-hs-main
$ ./ctest
hello
答案 1 :(得分:-2)
我认为您需要的是System.IO.Unsafe.unsafePerformIO
,然后再将IO CString转换为CString,然后再将CString发送到C。newCString会将Haskell字符串转换为IO CString。因此,System.IO.Unsafe.unsafePerformIO $ newCString a
可以传递到C例程,该例程将接受类型为char*
的输入。如果您的C例程返回静态char*
,则System.IO.Unsafe.unsafePerformIO $ peekCString
将给您Haskell字符串。您需要导入System.IO.Unsafe
。 unsafePerformIO
在Foreign.C.String
(或Foreign.C.Types
?)中有一个不推荐使用的实现,因此您必须使用完整路径。在找到unsafePerformIO
之前,我经历了一段地狱-可能是因为人们对某种危险的东西过敏,以至于将不纯声明为纯净。如果newCString
反复使用而没有清洁,可能会导致内存泄漏。 withCString
可能是一个更好的选择-稍后会了解。