连接 Haskell 和 C++
Interfacing Haskell and C++
我想在 C++ 程序中调用一些 Haskell 函数。
为此,我申请了 these
说明并根据我的代码和系统进行调整。
目前我有以下内容:
- Main.cpp
- 共享头文件和 cpp 文件
- 生成文件
- cpp/
- 一些cpp和头文件
- haskell/
- hello.hs
生成文件如下:
CPP_SOURCES = main.cpp textures.cpp cpp/game.cpp \
cpp/piece.cpp cpp/factories.cpp cpp/utils.cpp
HASKELL_SOURCES = haskell/hello.hs
all: main; ./main
main: $(CPP_SOURCES) HaskellPart.o; g++ \
-lsfml-graphics \
-lsfml-window \
-lsfml-system \
-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/rts \
-lHSrts \
-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 \
-fno-stack-protector \
-Wall \
-o main $(CPP_SOURCES) haskell/hello.o
HaskellPart.o: $(HASKELL_SOURCES); ghc -fforce-recomp -fPIC $(HASKELL_SOURCES)
clean: ; rm -rf main && rm -rf haskell/*.o && \
rm -rf haskell/*.hi && rm -rf haskell/*_stub.h
我所做的是:
- 添加
-I/usr/lib/ghc/include
以允许 g++ 查找 HsFFI.h
- 更新库路径
- 在 ghc 参数中添加
-fPIC
以避免符号错误。
但是,我最终得到以下输出:
$ make
ghc -fforce-recomp -fPIC haskell/hello.hs
[1 of 1] Compiling Hello ( haskell/hello.hs, haskell/hello.o )
g++ \
-lsfml-graphics \
-lsfml-window \
-lsfml-system \
-I/usr/lib/ghc/include \
-liconv \
-L/usr/lib/ghc/rts \
-lHSrts \
-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 \
-fno-stack-protector \
-Wall \
-o main main.cpp textures.cpp cpp/game.cpp cpp/piece.cpp cpp/factories.cpp cpp/utils.cpp haskell/hello.o
/tmp/ccHPRuDY.o: In function `main':
main.cpp:(.text+0x358): undefined reference to `hs_init'
main.cpp:(.text+0x375): undefined reference to `hs_exit'
haskell/hello.o: In function `sRs_info':
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x2e): undefined reference to `newCAF'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x3e): undefined reference to `stg_bh_upd_frame_info'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x54): undefined reference to `ghczmprim_GHCziCString_unpackCStringzh_closure'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x5d): undefined reference to `stg_ap_n_fast'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x96): undefined reference to `newCAF'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0xa6): undefined reference to `stg_bh_upd_frame_info'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0xbc): undefined reference to `base_SystemziIO_putStrLn_closure'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0xc5): undefined reference to `stg_ap_p_fast'
haskell/hello.o: In function `helloFromHaskell':
(.text+0xd8): undefined reference to `rts_lock'
haskell/hello.o: In function `helloFromHaskell':
(.text+0xee): undefined reference to `base_GHCziTopHandler_runIO_closure'
haskell/hello.o: In function `helloFromHaskell':
(.text+0xf9): undefined reference to `rts_apply'
haskell/hello.o: In function `helloFromHaskell':
(.text+0x10f): undefined reference to `rts_evalIO'
haskell/hello.o: In function `helloFromHaskell':
(.text+0x122): undefined reference to `rts_checkSchedStatus'
haskell/hello.o: In function `helloFromHaskell':
(.text+0x12e): undefined reference to `rts_unlock'
haskell/hello.o: In function `stginit_export_Hello_zdfstableZZC0ZZCmainZZCHelloZZChelloFromHaskell':
ghc_3.c:(.text+0x144): undefined reference to `foreignExportStablePtr'
haskell/hello.o: In function `sRs_closure':
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x40): undefined reference to `stg_IND_STATIC_info'
haskell/hello.o: In function `rHM_closure':
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x60): undefined reference to `ghczmprim_GHCziTypes_TrNameS_static_info'
haskell/hello.o: In function `rI0_closure':
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x70): undefined reference to `ghczmprim_GHCziTypes_TrNameS_static_info'
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x80): undefined reference to `ghczmprim_GHCziTypes_Module_static_info'
haskell/hello.o: In function `SRD_srt':
/tmp/ghc9fcb_0/ghc_7.o:(.data.rel.ro+0x0): undefined reference to `ghczmprim_GHCziCString_unpackCStringzh_closure'
/tmp/ghc9fcb_0/ghc_7.o:(.data.rel.ro+0x8): undefined reference to `base_SystemziIO_putStrLn_closure'
collect2: error: ld returned 1 exit status
makefile:17: recipe for target 'main' failed
make: *** [main] Error 1
知道我做错了什么吗?
谢谢!
编辑:
根据n.m的回答,我改变了g++参数的顺序。这是新的 makefile:
CPP_SOURCES = main.cpp textures.cpp cpp/game.cpp cpp/piece.cpp cpp/factories.cpp cpp/utils.cpp
HASKELL_SOURCES = haskell/hello.hs
CFLAGS = -Wall -g -fno-stack-protector
all: main; ./main
main: $(CPP_SOURCES) HaskellPart.o; g++ \
$(CFLAGS) -o main $(CPP_SOURCES) haskell/hello.o \
-lsfml-graphics \
-lsfml-window \
-lsfml-system \
-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.o: $(HASKELL_SOURCES); ghc -fforce-recomp -fPIC $(HASKELL_SOURCES)
clean: ; rm -rf main && rm -rf haskell/*.o && rm -rf haskell/*.hi && rm -rf haskell/*_stub.h
但它引发了另一个错误:
/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Itimer.o): undefined reference to symbol 'timer_settime@@GLIBC_2.3.3'
根据 this 线程,我添加了 -lrt
但得到:
/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Linker.o): undefined reference to symbol 'dlsym@@GLIBC_2.2.5'
所以根据 thread I added -ldl
and now it's a big mess...
编辑:赏金
伙计们,我要增加一笔赏金,花费我低额声誉的很大一部分,因为我无法完成这项工作,而且我真的需要这个。
这是一个与学校相关的项目,但我必须准确地说这不是作弊,因为主题只说:"write a large program in c++ and write the same program in haskell"。
为这两个程序制作一个通用的图形界面是我的决定,不在课程范围内。
除此之外,我认为互联网上缺乏关于这个主题的文档,我的老师告诉我他从来没有设法做到这一点,所以对 [=102 的 g++ 配置有一个结构化的答案会很有帮助=] 对外出口。
感谢您的帮助。
只是尝试 link 回答我对这个问题的其他版本的回答,但它决定自动将其添加为评论...不是特别有用,因为将来找到此主题的人可能只会看到它没有答案,所以我会粘贴完整的答案。
不确定它是否真的在你的文件中,或者它是否只是在你提出问题的版本中,但“// hello.hs”不会编译。评论是 -- 在 Haskell 而不是 //.
总之进入有趣的部分...
首先,您需要将 HsFFI.h 头文件导入到您的 C++ 代码中。
#include <iostream>
#include "Hello_stub.h"
#include <HsFFI.h>
然后用ghc link 编译后的文件。打开命令提示符/终端并浏览包含 C++ 和 Haskell 文件的目录。然后运行以下命令:
ghc -c -XForeignFunctionInterface -O hello.hs
g++ -c -O main.cpp -I "C:\Program Files\Haskell Platform.10.3\lib\include"
ghc -no-hs-main hello.o main.o -lstdc++
第二条命令中的文件路径指向包含 HsFFI.h 文件的目录。
运行 main 然后输出:
Hello from C++
Hello from Haskell
我想在 C++ 程序中调用一些 Haskell 函数。
为此,我申请了 these 说明并根据我的代码和系统进行调整。
目前我有以下内容:
- Main.cpp
- 共享头文件和 cpp 文件
- 生成文件
- cpp/
- 一些cpp和头文件
- haskell/
- hello.hs
生成文件如下:
CPP_SOURCES = main.cpp textures.cpp cpp/game.cpp \
cpp/piece.cpp cpp/factories.cpp cpp/utils.cpp
HASKELL_SOURCES = haskell/hello.hs
all: main; ./main
main: $(CPP_SOURCES) HaskellPart.o; g++ \
-lsfml-graphics \
-lsfml-window \
-lsfml-system \
-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/rts \
-lHSrts \
-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 \
-fno-stack-protector \
-Wall \
-o main $(CPP_SOURCES) haskell/hello.o
HaskellPart.o: $(HASKELL_SOURCES); ghc -fforce-recomp -fPIC $(HASKELL_SOURCES)
clean: ; rm -rf main && rm -rf haskell/*.o && \
rm -rf haskell/*.hi && rm -rf haskell/*_stub.h
我所做的是:
- 添加
-I/usr/lib/ghc/include
以允许 g++ 查找HsFFI.h
- 更新库路径
- 在 ghc 参数中添加
-fPIC
以避免符号错误。
但是,我最终得到以下输出:
$ make
ghc -fforce-recomp -fPIC haskell/hello.hs
[1 of 1] Compiling Hello ( haskell/hello.hs, haskell/hello.o )
g++ \
-lsfml-graphics \
-lsfml-window \
-lsfml-system \
-I/usr/lib/ghc/include \
-liconv \
-L/usr/lib/ghc/rts \
-lHSrts \
-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 \
-fno-stack-protector \
-Wall \
-o main main.cpp textures.cpp cpp/game.cpp cpp/piece.cpp cpp/factories.cpp cpp/utils.cpp haskell/hello.o
/tmp/ccHPRuDY.o: In function `main':
main.cpp:(.text+0x358): undefined reference to `hs_init'
main.cpp:(.text+0x375): undefined reference to `hs_exit'
haskell/hello.o: In function `sRs_info':
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x2e): undefined reference to `newCAF'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x3e): undefined reference to `stg_bh_upd_frame_info'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x54): undefined reference to `ghczmprim_GHCziCString_unpackCStringzh_closure'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x5d): undefined reference to `stg_ap_n_fast'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0x96): undefined reference to `newCAF'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0xa6): undefined reference to `stg_bh_upd_frame_info'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0xbc): undefined reference to `base_SystemziIO_putStrLn_closure'
/tmp/ghc9fcb_0/ghc_7.o:(.text+0xc5): undefined reference to `stg_ap_p_fast'
haskell/hello.o: In function `helloFromHaskell':
(.text+0xd8): undefined reference to `rts_lock'
haskell/hello.o: In function `helloFromHaskell':
(.text+0xee): undefined reference to `base_GHCziTopHandler_runIO_closure'
haskell/hello.o: In function `helloFromHaskell':
(.text+0xf9): undefined reference to `rts_apply'
haskell/hello.o: In function `helloFromHaskell':
(.text+0x10f): undefined reference to `rts_evalIO'
haskell/hello.o: In function `helloFromHaskell':
(.text+0x122): undefined reference to `rts_checkSchedStatus'
haskell/hello.o: In function `helloFromHaskell':
(.text+0x12e): undefined reference to `rts_unlock'
haskell/hello.o: In function `stginit_export_Hello_zdfstableZZC0ZZCmainZZCHelloZZChelloFromHaskell':
ghc_3.c:(.text+0x144): undefined reference to `foreignExportStablePtr'
haskell/hello.o: In function `sRs_closure':
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x40): undefined reference to `stg_IND_STATIC_info'
haskell/hello.o: In function `rHM_closure':
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x60): undefined reference to `ghczmprim_GHCziTypes_TrNameS_static_info'
haskell/hello.o: In function `rI0_closure':
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x70): undefined reference to `ghczmprim_GHCziTypes_TrNameS_static_info'
/tmp/ghc9fcb_0/ghc_7.o:(.data+0x80): undefined reference to `ghczmprim_GHCziTypes_Module_static_info'
haskell/hello.o: In function `SRD_srt':
/tmp/ghc9fcb_0/ghc_7.o:(.data.rel.ro+0x0): undefined reference to `ghczmprim_GHCziCString_unpackCStringzh_closure'
/tmp/ghc9fcb_0/ghc_7.o:(.data.rel.ro+0x8): undefined reference to `base_SystemziIO_putStrLn_closure'
collect2: error: ld returned 1 exit status
makefile:17: recipe for target 'main' failed
make: *** [main] Error 1
知道我做错了什么吗?
谢谢!
编辑:
根据n.m的回答,我改变了g++参数的顺序。这是新的 makefile:
CPP_SOURCES = main.cpp textures.cpp cpp/game.cpp cpp/piece.cpp cpp/factories.cpp cpp/utils.cpp
HASKELL_SOURCES = haskell/hello.hs
CFLAGS = -Wall -g -fno-stack-protector
all: main; ./main
main: $(CPP_SOURCES) HaskellPart.o; g++ \
$(CFLAGS) -o main $(CPP_SOURCES) haskell/hello.o \
-lsfml-graphics \
-lsfml-window \
-lsfml-system \
-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.o: $(HASKELL_SOURCES); ghc -fforce-recomp -fPIC $(HASKELL_SOURCES)
clean: ; rm -rf main && rm -rf haskell/*.o && rm -rf haskell/*.hi && rm -rf haskell/*_stub.h
但它引发了另一个错误:
/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Itimer.o): undefined reference to symbol 'timer_settime@@GLIBC_2.3.3'
根据 this 线程,我添加了 -lrt
但得到:
/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Linker.o): undefined reference to symbol 'dlsym@@GLIBC_2.2.5'
所以根据-ldl
and now it's a big mess...
编辑:赏金
伙计们,我要增加一笔赏金,花费我低额声誉的很大一部分,因为我无法完成这项工作,而且我真的需要这个。
这是一个与学校相关的项目,但我必须准确地说这不是作弊,因为主题只说:"write a large program in c++ and write the same program in haskell"。
为这两个程序制作一个通用的图形界面是我的决定,不在课程范围内。
除此之外,我认为互联网上缺乏关于这个主题的文档,我的老师告诉我他从来没有设法做到这一点,所以对 [=102 的 g++ 配置有一个结构化的答案会很有帮助=] 对外出口。
感谢您的帮助。
只是尝试 link 回答我对这个问题的其他版本的回答,但它决定自动将其添加为评论...不是特别有用,因为将来找到此主题的人可能只会看到它没有答案,所以我会粘贴完整的答案。
不确定它是否真的在你的文件中,或者它是否只是在你提出问题的版本中,但“// hello.hs”不会编译。评论是 -- 在 Haskell 而不是 //.
总之进入有趣的部分...
首先,您需要将 HsFFI.h 头文件导入到您的 C++ 代码中。
#include <iostream>
#include "Hello_stub.h"
#include <HsFFI.h>
然后用ghc link 编译后的文件。打开命令提示符/终端并浏览包含 C++ 和 Haskell 文件的目录。然后运行以下命令:
ghc -c -XForeignFunctionInterface -O hello.hs
g++ -c -O main.cpp -I "C:\Program Files\Haskell Platform.10.3\lib\include"
ghc -no-hs-main hello.o main.o -lstdc++
第二条命令中的文件路径指向包含 HsFFI.h 文件的目录。
运行 main 然后输出:
Hello from C++
Hello from Haskell