如何将字符串从Haskell传递到C?
我所要做的就是将一个纯文本字符串从Haskell传递到C。然而,它说[Char]是一个不可接受的返回类型。我找不到他们为什么会这么认为,也找不到什么是可接受的回报类型 我正在尝试制作一个非常简单的操作系统映像,可以用Qemu启动 有人知道怎么做吗?谢谢如何将字符串从Haskell传递到C?,c,haskell,ffi,C,Haskell,Ffi,我所要做的就是将一个纯文本字符串从Haskell传递到C。然而,它说[Char]是一个不可接受的返回类型。我找不到他们为什么会这么认为,也找不到什么是可接受的回报类型 我正在尝试制作一个非常简单的操作系统映像,可以用Qemu启动 有人知道怎么做吗?谢谢 {-# LANGUAGE ForeignFunctionInterface #-} module Hello where import Foreign import Foreign.C.String i
{-# 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
withCString :: String -> (CString -> IO a) -> IO a
从String
转到CString
:
peekCString :: CString -> IO String
withCString :: String -> (CString -> IO a) -> IO a
也有黑线鳕的文档
可以在外部
声明中使用的类型的常规列表指定为的一部分
编辑
好的,这里有一个非常小的例子,说明了您可以做的一件事,多少是基于您的示例代码。创建包含以下内容的Haskell文件CTest.hs
:
module CTest where
import Foreign.C
hello :: IO CString
hello = newCString "hello"
foreign export ccall hello :: IO CString
#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;
}
然后创建一个包含以下内容的C文件ctest.C
:
module CTest where
import Foreign.C
hello :: IO CString
hello = newCString "hello"
foreign export ccall hello :: IO CString
#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;
}
我认为您需要的是
System.IO.Unsafe.unsafePerformIO
在将CString发送到C之前将IO CString转换为CString。newCString将把Haskell字符串转换为IO CString。因此,System.IO.Unsafe.unsafePerformIO$newCString a
可以被传递到您的C例程,该例程将接受类型为char*
的输入。如果您的C例程返回staticchar*
,则System.IO.Unsafe.unsafePerformIO$peek cstring
将返回一个Haskell字符串。您需要导入System.IO.Unsafe
unsafePerformIO
在Foreign.C.String
(或Foreign.C.Types
?)中有一个不推荐使用的实现,因此您必须使用完整路径。我花了很长时间才发现不安全的行为
——可能是因为人们对某种非常危险的东西过敏,以至于强迫宣布不纯净为纯净newCString
如果在不清洁的情况下重复使用,可能会导致内存泄漏withCString
可能是一个更好的选择-稍后将了解这一点。我尝试过这个,但它仍然说[Char]是不可接受的,除此之外。我完全不熟悉Haskell和函数式编程,但不熟悉C或汇编。我把我当前的代码放在第一篇文章中。你的代码有几个问题hello
是一个字符串文字,但您已经为它指定了一个函数类型。而String
仍然出现在导出实体的类型中。您可能需要先阅读Haskell外部函数接口的一些介绍。我创建了一个hello函数,这样我可以导出它并从C调用它,让它返回一个字符串/字符数组。我读了FFI的介绍,但不太理解,因为他们没有解释如何导出Haskell函数。你需要在某个时候让asm调用hs_init()。没办法了!哦,但你也能做到!而且(后者是一个很好的概念证明,但是Research和Bitrotterd afaik——前者现在适合在现实世界中使用)这听起来不是一个好主意<代码>withCString帮助管理内存属性。如果使用newCString
,则必须手动释放它。这并不一定不好,但如果调用unsafePerformIO(newCString s)
则情况会变得更糟:您可能会发现很难确定何时可以安全地释放字符串。顺便说一句:作为一个使用unsafePerformIO
和类似函数做过一些非琐碎工作的人,我想用最强烈的措辞说,它们只应该在真正必要的时候使用,而且几乎不应该被初学者使用(是的,有外国金融机构的例外,但这不是一个例外)。即使是真正的Haskell专家,比如GHC的首席开发人员,在使用unsafePerformIO
时也会犯一些微妙但严重的错误。人们对它过敏是因为它具有高度过敏性!