TLDR -- Calling D code from Haskell through the FFI works with DMD but not with GDC or LDC2.

The time consuming version:

Since D allows C to directly call it, if the D code is wrapped in extern (C){ ... }, I thought it should be possible to call such D code from Haskell using the FFI.

The FFI in Haskell allows directly calling C code given a header file, the name of a function, and its C-type. So I made a D file with the functions I want to call, FunctionsInD.d

    extern (C){
        int d_f(int x){
            return x+2;
        }
        int d_g(int x, int y){
            return x+y;
        }
    }

Then made a header file, FunctionsInD.h

    int d_f(int x);
    int d_g(int x, int y);

Then the Haskell wrapper ToD.hs:

    module ToD where

    import Foreign.C

    foreign import ccall "FunctionsInD.h d_f"
        c_f :: CInt -> CInt

    foreign import ccall "FunctionsInD.h d_g"
        c_g :: CInt -> CInt -> CInt

    h_f :: Int -> Int -- the "pure" haskell version
    h_f x = fromIntegral (c_f (fromIntegral x))

    h_g :: Int -> Int -> Int
    h_g x y = fromIntegral (c_g (fromIntegral x) (fromIntegral y))

For reasons I don't completely understand, you also need a fake main function, dummy.d:

    void main(){}

And a driver for test, Main.hs:

    module Main where

    import ToD

    main :: IO ()
    main = do
        let (a,b) = (h_f 3, h_g 3 4)
        sequence_ [putStrLn (show a), putStrLn (show b)]

To put this all together, here is the makefile.

    DC = dmd
    # DC = ldc2
    # DC = ldmd2
    # DC = gdc

    main: FunctionsInD.o FunctionsInD.h dummy.o
ghc Main.hs --make -o main_ffi_test FunctionsInD.o dummy.o -lphobos2

    clean:
        rm FunctionsInD.o dummy.o main_ffi_test

    FunctionsInD.o FunctionsInD.d:
        $(DC) -c FunctionsInD.d

    dummy.o: dummy.d
        $(DC) -c dummy.d

The question: if I comment out DC=dmd, and uncomment any of the other options, the build fails. The problem is that ghc complains of multiple definitions of main (not with DMD only GDC and LDC2). If I remove dummy.o from the ghc line, I get, undefined reference to _DMain.

But wait! It gets weirder. I can compile FunctionsInD.d with GDC or LDC2, as long as I compile dummy.d with DMD, everything works fine.

Once I get through this hump, I will try to get on with more interesting interfaces, like strings and structs.

Reply via email to