Re: Haskell calling D code through the FFI
Hi, thank you!! I have modified the program based on a previous suggestion. rt_init is called before using any D functionality and rt_term is called after using D functionality. I did this by: 1) Placing int rt_init(); and int rt_term(); into the header file that Haskell reads 2) Creating Haskell stubs foreign import ccall unsafe "FunctionsInD.h rt_init" d_init :: IO CInt foreign import ccall unsafe "FunctionsInD.h rt_term" d_term :: IO CInt And then in the Main haskell program, in main, the function starts with d_init and ends with d_term I'm pretty sure this is working nicely, because I can allocate structs with the "new" keyword in D, and this led to segfaults before using rt_init and rt_term. I think the problem I was having was trying to do this in a stupid way i.e. put wrappers around init and term on the D side. However, I still do not know how to compile without the using a fake main. Compiling with -c -lib does still give me a _Dmain undefined reference. I did dmd -c -lib FunctionsInD.d ghc --make Main.hs FunctionsInD.a -lphobos2 And get /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libphobos2.so: undefined reference to `_Dmain' On Wednesday, 6 August 2014 at 11:03:33 UTC, David Soria Parra via Digitalmars-d-learn wrote: Jon via Digitalmars-d-learn writes: So that does indeed solve some of the problems. However, using this method, when linking I get two errors, undefined reference rt_init() and rt_term() I had just put these methods in the header file. If I put wrappers around these functions and export I get the rt_init, rt_term is private. rt_init is part of druntime. You need to link druntime into your program in order to make it work.
Re: Haskell calling D code through the FFI
So that does indeed solve some of the problems. However, using this method, when linking I get two errors, undefined reference rt_init() and rt_term() I had just put these methods in the header file. If I put wrappers around these functions and export I get the rt_init, rt_term is private. On Tuesday, 5 August 2014 at 21:28:08 UTC, David Soria Parra wrote: On Monday, 4 August 2014 at 20:48:09 UTC, Jon wrote: For reasons I don't completely understand, you also need a fake main function, dummy.d: void main(){} Note that this is not necessary if you compile with -lib e.g.: dmd -lib -oflibtest.a test.d and then ghc Main.hs --make -omain libtest.a I don't have gdc or ldc installed but as far as I know ldc has a -lib flag as well.
Re: Haskell calling D code through the FFI
Oh great thank you. I think that might solve the majority of the confusion I was having. One thing I can't figure out though, is getting garbage collection to work as expected. If I have a function that allocates a pointer to a struct using new, I get an error on linking _dAlloc... not found. But maybe compiling as a lib will solve this too. On Tuesday, 5 August 2014 at 21:28:08 UTC, David Soria Parra wrote: On Monday, 4 August 2014 at 20:48:09 UTC, Jon wrote: For reasons I don't completely understand, you also need a fake main function, dummy.d: void main(){} Note that this is not necessary if you compile with -lib e.g.: dmd -lib -oflibtest.a test.d and then ghc Main.hs --make -omain libtest.a I don't have gdc or ldc installed but as far as I know ldc has a -lib flag as well.
Re: Haskell calling D code through the FFI
As a note, I can interact with strings as expected, but working with structs looks like it will take a little bit of work. On Monday, 4 August 2014 at 22:17:36 UTC, Jon wrote: Yes, thank you. That is exactly what I did. On Monday, 4 August 2014 at 21:48:40 UTC, safety0ff wrote: On Monday, 4 August 2014 at 21:35:21 UTC, Jon wrote: I get Error: core.runtime.rt_init is private. And Error: core.runtime.init is not accessible. I would add them to the header and Haskell wrapper (FunctionsInD.h and ToD.hs.) The signatures are: int rt_init(); int rt_term(); When it is linked it will find the symbols in druntime.
Re: Haskell calling D code through the FFI
Yes, thank you. That is exactly what I did. On Monday, 4 August 2014 at 21:48:40 UTC, safety0ff wrote: On Monday, 4 August 2014 at 21:35:21 UTC, Jon wrote: I get Error: core.runtime.rt_init is private. And Error: core.runtime.init is not accessible. I would add them to the header and Haskell wrapper (FunctionsInD.h and ToD.hs.) The signatures are: int rt_init(); int rt_term(); When it is linked it will find the symbols in druntime.
Re: Haskell calling D code through the FFI
I get Error: core.runtime.rt_init is private. And Error: core.runtime.init is not accessible. On Monday, 4 August 2014 at 21:22:37 UTC, safety0ff wrote: On Monday, 4 August 2014 at 21:14:17 UTC, Jon wrote: On Monday, 4 August 2014 at 21:10:46 UTC, safety0ff wrote: Don't forget to call rt_init: http://dlang.org/phobos/core_runtime.html#.rt_init Where/when should I call this? Before calling any D functions, but usually it's simplest to call it early in main. It initializes the GC and notifies the D runtime of its existence. For simple D functions you might get away without calling it.
Re: Haskell calling D code through the FFI
On Monday, 4 August 2014 at 21:10:46 UTC, safety0ff wrote: Don't forget to call rt_init: http://dlang.org/phobos/core_runtime.html#.rt_init Where/when should I call this?
Haskell calling D code through the FFI
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.