从C++调用Haskell

8

我想从c++调用Haskell。

我尝试使用this的解释; 并在SO上提出了一个问题。

然而,我没有得到任何答案,所以我想重新制定一个最小、完整和可验证的示例。

我正在使用Debian,这是我拥有的(在同一文件夹中):

c++:

// main.cpp
#include <iostream>
#include "Hello_stub.h"

int main(int argc, char** argv) {
  hs_init(&argc, &argv);
  std::cout << "Hello from C++\n";
  helloFromHaskell();
  hs_exit();
  return 0;
}

Haskell:

// hello.hs
module Hello where

foreign export ccall helloFromHaskell :: IO ()

helloFromHaskell :: IO ()
helloFromHaskell = putStrLn "Hello from Haskell"

MakeFile:

CPP_SOURCES = main.cpp
HASKELL_SOURCES = Hello.hs
CFLAGS = -Wall -g -fno-stack-protector
HFLAGS = -fforce-recomp

all: main; ./main

main: $(CPP_SOURCES) HaskellPart; g++ \
    $(CFLAGS) -o main $(CPP_SOURCES) Hello.o \
    -I/usr/lib/ghc/include \
    -liconv \
    -I/usr/lib/ghc/ghc-8.0.1/include \
    -L/usr/lib/ghc/ghc-8.0.1 \
    -L/usr/lib/ghc/base-4.9.0.0 \
    -lHSbase-4.9.0.0 \
    -L/usr/lib/ghc/ghc-prim-0.5.0.0 \
    -lHSghc-prim-0.5.0.0 \
    -L/usr/lib/ghc/integer-gmp-1.0.0.1 \
    -lHSinteger-gmp-1.0.0.1 \
    -lHSghc-prim-0.5.0.0 \
    -L/usr/lib/ghc/rts \
    -lHSrts \

HaskellPart: $(HASKELL_SOURCES); ghc $(HFLAGS) $(HASKELL_SOURCES)

clean: ; rm -rf main && rm -rf *.o && rm -rf *.hi && rm -rf *_stub.h

这里是output。看起来是一堆形式为错误的东西。

/usr/bin/ld: Hello.o: relocation R_X86_64_32S against symbol `stg_bh_upd_frame_info' can not be used when making a shared object; recompile with -fPIC

有什么问题吗?谢谢你的帮助!


1
我昨天花了一整天做这个,最终成功了,所以这是可能的。我没有遇到你看到的错误,但错误提示似乎在告诉你在编译器标志中添加“-fPIC”。(希望这不意味着在编译 GHC 时) - luqui
2
另一种选择(我没有使用过)听说可行的方法是将 ghc 用作链接器。这样,您就不需要对所有 -L 进行设置了。例如:g++ -c main.cpp; ghc Hello.hs main.o -o main 或类似命令。 - luqui
等等——你的 makefile 中似乎有一些错误。你提到了 HaskellPart.o,但是没有 HaskellPart.hs。而且 Hello.og++ 命令行上,尽管表面上需要 HaskellPart.o。清空你的项目目录,然后再试一次(这样你就不会被过时的目标文件误导了)。此外,-c 不应该在 ghc 命令行上吗? - luqui
@luqui 是的,我明白。我已经重命名它以保持清晰。我很渴望找到一个解决方案 :/ - Maxime VAST
1
事情需要多长时间就要花多长时间。一步一个脚印。;-) - luqui
显示剩余4条评论
1个回答

2

我不确定这个内容是否实际存在于您的文件中,还是只在您提问时出现,但 "// hello.hs" 无法编译。在 Haskell 中,注释应该使用 -- 而不是 //。

无论如何,接下来进入有趣的部分...

首先,您需要将 HsFFI.h 头文件导入到您的 C++ 代码中。

#include <iostream>
#include "Hello_stub.h"
#include <HsFFI.h>

编译完成后,使用ghc将文件链接起来。打开命令提示符/终端并导航到包含您的C++和Haskell文件的目录。然后运行以下命令:

ghc -c -XForeignFunctionInterface -O hello.hs
g++ -c -O main.cpp -I "C:\Program Files\Haskell Platform\7.10.3\lib\include"                         
ghc -no-hs-main hello.o main.o -lstdc++

在第二条命令中的文件路径是指包含 HsFFI.h 文件的目录。
运行 main 后,输出如下:
Hello from C++
Hello from Haskell

太棒了,非常感谢!你认为 Github 教程有问题还是只适用于 Mac OS?你有进一步的解释吗? - Maxime VAST
1
@MaximeVAST 我不能确定,因为我对CMake的了解不是很深。这个教程是2014年的,所以可能已经过时了。尝试在CMake文件中将-shared和-dynamic(也许还有-fPIC)添加到你的Haskell标志中,看看你原来的方法是否有效。 - James Burton

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