[英]How to pass a string from Haskell to C?
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.我想要做的就是将一个纯文本字符串从 Haskell 传递给 C。但是,它说 [Char] 是一种不可接受的返回类型。 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.我正在尝试制作一个可以使用 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
.你想要一个
CString
。
Going from CString
to String
:从
CString
到String
:
peekCString :: CString -> IO String
Going from String
to CString
:从
String
到CString
:
withCString :: String -> (CString -> IO a) -> IO a
There's also Haddock documentation for module Foreign.C.String
.还有模块
Foreign.C.String
Haddock 文档。
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 .可以在
foreign
声明中使用的类型的一般列表在 Haskell 报告中指定为外部函数接口的一部分。
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:使用以下内容创建 Haskell 文件
CTest.hs
:
module CTest where
import Foreign.C
hello :: IO CString
hello = newCString "hello"
foreign export ccall hello :: IO CString
Then create a C file ctest.c
with the following contents:然后创建一个包含以下内容的 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;
}
Then compile and run as follows:然后编译运行如下:
$ ghc CTest
[1 of 1] Compiling CTest ( CTest.hs, CTest.o )
$ ghc -o ctest ctest.c CTest.o -no-hs-main
$ ./ctest
hello
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.我认为你需要的是
System.IO.Unsafe.unsafePerformIO
在将 CString 发送到 C 之前将 IO CString 转换为 CString。newCString 会将 Haskell 字符串转换为 IO CString。 Thus System.IO.Unsafe.unsafePerformIO $ newCString a
can be passed to your C routine which will accept input of type char*
.因此
System.IO.Unsafe.unsafePerformIO $ newCString a
可以传递给您的 C 例程,该例程将接受char*
类型的输入。 If your C routine returns static char*
then System.IO.Unsafe.unsafePerformIO $ peekCString
will give you back a Haskell string.如果你的 C 例程返回 static
char*
那么System.IO.Unsafe.unsafePerformIO $ peekCString
会给你一个 Haskell 字符串。 You need to import System.IO.Unsafe
.您需要导入
System.IO.Unsafe
。 unsafePerformIO
has an implementation in Foreign.C.String
(or Foreign.C.Types
?) which is deprecated, so you have to use the full path. unsafePerformIO
在Foreign.C.String
(或Foreign.C.Types
?)中有一个已弃用的实现,因此您必须使用完整路径。 I had a hell of a time before I could find unsafePerformIO
- probably because people are allergic to something that is so dangerous as to force declaration of impure to pure.在我找到
unsafePerformIO
之前,我unsafePerformIO
很unsafePerformIO
——可能是因为人们对某些危险的东西过敏,以至于强制声明不纯为纯。 newCString
can lead to memory leaks if used repeatedly without cleaning. newCString
如果不清理就重复使用会导致内存泄漏。 withCString
may be a better option - will learn that later. withCString
可能是更好的选择 - 稍后会学习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.