I'd like to call some Haskell functions in a c++ program.
In order to do so, i have applied these instructions and adapted them to my code and system.
What I have for the moment is the following:
The make file is the following:
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
What I have done is:
-I/usr/lib/ghc/include
to allow g++ to find HsFFI.h
-fPIC
to the ghc arguments to avoid symbol errors.However, I end up with the following output:
$ 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
Any idea of what I am doing wrong ?
Thank you!
EDIT :
According to n.m answer, I changed the order of g++ arguments. Here's the new 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
But it raised another error:
/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Itimer.o): undefined reference to symbol 'timer_settime@@GLIBC_2.3.3'
According to this thread, I added -lrt
but got:
/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Linker.o): undefined reference to symbol 'dlsym@@GLIBC_2.2.5'
So according to this thread I added -ldl
and now it's a big mess...
EDIT : BOUNTY
Guys I'm adding a bounty spending a large proportion of my low amount of reputation because I can't manage to make this work and really need this.
This is for a school related project but I have to precise that this is not cheating as subject only says: "write a large program in c++ and write the same program in haskell".
Making a common graphical interface for both programs is my decision and is out of the scope of the coursework.
Beside that, I think there a lack of documentation on this subject on internet, my teacher told me he never managed to do it so it would be helpful to have a constructed answer on the configuration of g++ with Haskell Foreign Export.
Thanks you for your help.
Tried just linking to my answer on your other version of this question but it decided to automatically make it a comment... Not particularly helpful because people who find this thread in the future might just see it as unanswered so I'll paste the full answer instead.
Not sure whether that's actually in your file or whether it's just in the version you put in your question but "// hello.hs" won't compile. Comments are -- in Haskell not //.
Anyway on to the interesting part...
First you need to import the HsFFI.h header file into your C++ code.
#include <iostream>
#include "Hello_stub.h"
#include <HsFFI.h>
Then use ghc to link the files after compiling them. Open a command prompt / terminal and navigate the directory containing your C++ and Haskell files. Then run the following commands:
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++
The filepath in the second command is to the directory containing the HsFFI.h file.
Running main then outputs:
Hello from C++
Hello from Haskell
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With