Haskell内联C/C++调用Haskell函数

3

我在一个小例子中使用inline-c-cpp来反转字符串:

[C.block| void {
        static char strTest[128] = "Hello, Haskell!";
        c_func();
  } |]

这里是Haskell代码:

reverseIO :: BS.ByteString -> IO BS.ByteString
reverseIO str = return $ BS.reverse str

c_func() 在另一个我通过C.include "test.c"引入的C文件中定义。 在那个test.c文件中,我调用了

$fun:(char * (*reverseIO)(char * ))(strTest)

我遇到了几个错误:

 error: use of undeclared identifier 'reverseIO'
              $fun:(char (*reverseIO)(char * ))(strTest)
                           ^

有人可以帮我把这个搞对吗?

更新: 最终我使用了正确的C函数指针语法,让它运行起来了。

  [C.block| void {
           c_func($fun:(char* (*reverseIO)(char*)));
                         } |]

但我仍然有类型问题:

Couldn't match typeBS.ByteString’ with ‘GHC.Ptr.Ptr CChar
  Expected type: GHC.Ptr.Ptr CChar -> IO (GHC.Ptr.Ptr CChar)
    Actual type: BS.ByteString -> IO BS.ByteString

1
你想让你的C代码调用Haskell函数吗?我以前没有使用过inline-c,而且认为它只能用于调用C而不是返回。不管那个,你已经foreign export了你的reverseIO函数吗?当GHC编译Haskell时,函数不会直接转换为符号,因此如果没有外部导出,链接时将没有reverseIO符号或编译原型。 - Thomas M. DuBuisson
我不熟悉inline-c,但是String不是char *。也许你需要使用字节串,这似乎是由inline-c支持的。请注意,传递(字节)字符串可能需要处理C级别的分配。 - chi
@ThomasM.DuBuisson 是的,我使用inline-c来调用GUI库(Dear imgui)。其余的事情我想在Haskell中完成,并在C中调用这些Haskell函数。关于Foreign export,正如你所提到的,我在fpcomplete教程中没有看到这个内容:https://www.fpcomplete.com/blog/2015/05/inline-c。但让我深入探究一下这个方向。谢谢。 - McBear Holden
@chi 很好的建议,我已经切换到BS了。 - McBear Holden
1个回答

4
最终成功了:
import           Data.Monoid           ((<>))
import           Foreign.C.String
import qualified Language.C.Inline.Cpp as C

C.context (C.cppCtx <> C.baseCtx  <>C.funCtx)

C.include "pageturnerui.cpp"

someFunc :: IO ()
someFunc = do
  let reverseIO :: CString -> IO CString
      reverseIO cs = peekCString cs >>= return. reverse >>= newCString

  [C.block| void {
      pageturnerui($fun:(char* (*reverseIO)(char *)));
                         } |]

在我的pageturnerui.cpp文件中:
int pageturnerui(char* (*foo)(char*))
{
...
            static char strTest[128] = "Hello, Haskell!";

            if (ImGui::Button("Button")) {
              strcpy(strTest, foo(strTest));
            }
...
}

提示:我的代码并不代表最佳实践。我还没有足够的经验来提供建议。只是展示它可以编译、运行,并且没有崩溃。


你介意在 pageturnerui.cpp 中添加一些最小工作代码吗?这个答案对于刚开始使用内联C-CPP的人来说可能非常有价值。 - luqui
@luqui 完成。希望这对你有用。 - McBear Holden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接