Haskell calling D code through the FFI

Jon via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Aug 4 13:48:08 PDT 2014


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.


More information about the Digitalmars-d-learn mailing list