10

我要做的就是将纯文本字符串从 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
4

2 回答 2

15

你想要一个CString.

CStringString:

peekCString :: CString -> IO String

StringCString:

withCString :: String -> (CString -> IO a) -> IO a

还有针对moduleForeign.C.String的 Haddock 文档。

可以在foreign声明中使用的一般类型列表在 Haskell 报告中指定为外部函数接口的一部分。

编辑

好的,这是您可以做的一个非常小的示例,在某种程度上基于您的示例代码。创建一个CTest.hs包含以下内容的 Haskell 文件:

module CTest where

import Foreign.C

hello :: IO CString
hello = newCString "hello"

foreign export ccall hello :: IO CString

然后创建一个ctest.c包含以下内容的 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
于 2013-07-23T13:57:57.473 回答
-2

我认为您需要System.IO.Unsafe.unsafePerformIO在将 CString 发送到 C 之前将 IO CString 转换为 CString。newCString 会将 Haskell 字符串转换为 IO CString。因此System.IO.Unsafe.unsafePerformIO $ newCString a可以传递给您的 C 例程,该例程将接受 type 的输入char*。如果你的 C 例程返回静态char*,那么System.IO.Unsafe.unsafePerformIO $ peekCString会给你一个 Haskell 字符串。您需要导入System.IO.Unsafe. unsafePerformIOForeign.C.String(或Foreign.C.Types?)中有一个已弃用的实现,因此您必须使用完整路径。我花了很长时间才找到unsafePerformIO——可能是因为人们对某种危险的东西过敏,以至于迫使人们宣布不纯为纯。 newCString如果重复使用而不清理,可能会导致内存泄漏。withCString可能是一个更好的选择 - 稍后会知道。

于 2018-09-08T03:54:48.543 回答