[英]How to pass a string from Haskell to C?
我想要做的就是将一个纯文本字符串从 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
你想要一个CString
。
从CString
到String
:
peekCString :: CString -> IO String
从String
到CString
:
withCString :: String -> (CString -> IO a) -> IO a
还有模块Foreign.C.String
Haddock 文档。
可以在foreign
声明中使用的类型的一般列表在 Haskell 报告中指定为外部函数接口的一部分。
好的,这是您可以做的事情的一个很小的例子,有点基于您的示例代码。 使用以下内容创建 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
我认为你需要的是System.IO.Unsafe.unsafePerformIO
在将 CString 发送到 C 之前将 IO CString 转换为 CString。newCString 会将 Haskell 字符串转换为 IO CString。 因此System.IO.Unsafe.unsafePerformIO $ newCString a
可以传递给您的 C 例程,该例程将接受char*
类型的输入。 如果你的 C 例程返回 static char*
那么System.IO.Unsafe.unsafePerformIO $ peekCString
会给你一个 Haskell 字符串。 您需要导入System.IO.Unsafe
。 unsafePerformIO
在Foreign.C.String
(或Foreign.C.Types
?)中有一个已弃用的实现,因此您必须使用完整路径。 在我找到unsafePerformIO
之前,我unsafePerformIO
很unsafePerformIO
——可能是因为人们对某些危险的东西过敏,以至于强制声明不纯为纯。 newCString
如果不清理就重复使用会导致内存泄漏。 withCString
可能是更好的选择 - 稍后会学习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.