Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 04, 2014 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. |
August 04, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jon | Don't forget to call rt_init: http://dlang.org/phobos/core_runtime.html#.rt_init |
August 04, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to safety0ff | 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?
|
August 04, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jon | 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.
|
August 04, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to safety0ff | 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.
|
August 04, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jon | 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.
|
August 04, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to safety0ff | 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.
|
August 05, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jon | 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.
|
August 05, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jon | 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.
|
August 05, 2014 Re: Haskell calling D code through the FFI | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Soria Parra | 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.
|
Copyright © 1999-2021 by the D Language Foundation