8

I'm trying to call Haskell from c++.

I tried to use this explanation; and already asked one question on SO.

However, I haven't got any answer so I'd like to reformulate to a Minimal, Complete, and Verifiable example.

I'm using Debian and this is what I have (In the same folder):

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

Here's the output. It seems to be a bunch of errors of the form

/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

What's wrong? Thank you for your help !

9
  • 1
    I just spent all day doing this yesterday, and succeeded, so it is possible. I didn't hit the error you are seeing, but the errors seem to be telling you to add -fPIC to your compiler flags. (I hope it doesn't mean when compiling GHC) Commented Mar 29, 2017 at 18:17
  • 2
    Another option (which wasn't available to me) that I heard worked is to use ghc as your linker. Then you don't need to futz with all the -L stuff. I.e. g++ -c main.cpp; ghc Hello.hs main.o -o main or something Commented Mar 29, 2017 at 18:23
  • @luqui Thank you for taking the time. Do you have any link for this other option? About -fPIC, I have tried to add it but it doesn't change anything. My guess is that the error come from the libraries and not from the compilation of my code. Do you have any working example ? Could you kindly share? Regards Commented Mar 29, 2017 at 18:25
  • I don't know how much my example is going to help, it's a pretty different context. OSX on Xcode. But the linker flags are here Commented Mar 29, 2017 at 18:27
  • 1
    things take as long as they take. One step at a time. ;-) Commented Mar 29, 2017 at 18:58

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome, thank you so much ! Would you say that the github tutorial is wrong or only adapted to mac os? Do you have any further explanation?
@MaximeVAST I can't really say because I don't know a huge amount about CMake. The tutorial is from 2014 so it might just be outdated. Try adding -shared and -dynamic (maybe -fPIC as well) to your Haskell flags in the CMake file and see if your original method works then.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.