Взаимодействие Haskell и С++

Я хотел бы назвать некоторые функции Haskell в С++-программе.

Чтобы сделать это, я применил эти  инструкции и адаптировали их к моему коду и системе.

То, что у меня есть на данный момент, следующее:

  • Main.cpp
  • Общие файлы заголовков и cpp
  • Makefile
  • CPP/
    • некоторые файлы cpp и заголовков
  • Haskell/
    • hello.hs

Файл make следующий:

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
  • обновить пути librairies
  • добавить -fPIC в аргументы ghc, чтобы избежать ошибок символов.

Однако в итоге я получаю следующий вывод:

    $ 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

Любая идея о том, что я делаю неправильно?

Спасибо!

EDIT:

В соответствии с ответом n.m я изменил порядок аргументов g++. Здесь новый make файл:

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 '[email protected]@GLIBC_2.3.3'

В соответствии с этой нитью я добавил -lrt, но получил:

/usr/bin/ld: /usr/lib/ghc/rts/libHSrts.a(Linker.o): undefined reference to symbol '[email protected]@GLIBC_2.2.5'

Итак, в соответствии с этой нитью я добавил -ldl и теперь большой беспорядок...

EDIT: BOUNTY

Ребята, я добавляю щедрость, тратящую большую часть моего низкого количества репутации, потому что я не могу справиться с этой работой и действительно нуждаюсь в этом.

Это для проекта, связанного с обучением, но я должен уточнить, что это не обман, поскольку субъект только говорит: "написать большую программу на С++ и написать ту же программу в haskell".

Создание общего графического интерфейса для обеих программ - это мое решение и выходит за рамки курсовой работы.

Кроме того, я думаю, что в Интернете нет документации по этому вопросу, мой учитель сказал мне, что он так и не смог это сделать, поэтому было бы полезно построить построенный ответ на конфигурацию g++ с Haskell Foreign Export.

Спасибо вам за помощь.

Ответ 1

Попробовал только ссылку на мой ответ на другую версию этого вопроса, но он решил автоматически сделать это замечанием... Не особенно полезно, потому что люди, которые найдут этот поток в будущем, могут просто увидеть его без ответа, чтобы я вставьте полный ответ.

Не уверен, действительно ли это в вашем файле, или только в версии, которую вы задали в своем вопросе, но "//hello.hs" не будет компилироваться. Комментарии - в Haskell not//.

В любом случае, на интересную часть...

Сначала вам нужно импортировать заголовочный файл HsFFI.h в свой код на С++.

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

Затем используйте ghc для связывания файлов после их компиляции. Откройте командную строку/терминал и перейдите в каталог, содержащий ваши файлы С++ и 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.

Выполнение основных выходов:

Hello from C++
Hello from Haskell