Difference between revisions of "Call D from Ruby using FFI"
(→Shorter Version) |
|||
Line 6: | Line 6: | ||
<syntaxhighlight lang="d"> | <syntaxhighlight lang="d"> | ||
+ | import std.stdio; | ||
+ | |||
extern(C) | extern(C) | ||
void hello() | void hello() |
Revision as of 10:31, 5 August 2016
Adam Ruppe posted this example in the Learn Forum. The goal is to write a function in D and call it from Ruby using the Ruby-FFI extension.
Shorter Version
Create the file "i.d" containing
import std.stdio;
extern(C)
void hello()
{
writeln("hi from D");
}
Compile it as a shared library. For example, to compile as a 64-bit shared library on Linux, you can do
dmd -shared -m64 -fPIC -defaultlib=libphobos2.so i.d
Create the file "d.rb" containing
require 'rubygems'
require 'ffi'
module DInterface
extend FFI::Library
ffi_lib './i.so'
attach_function :rt_init, :rt_init, [], :int
attach_function :rt_term, :rt_term, [], :int
attach_function :hello, :hello, [], :void
end
# call init
DInterface::rt_init
# our function
DInterface::hello
# terminate
DInterface::rt_term
Run the Ruby file:
ruby ./d.rb
You should see
hi from D
If you have the phobos shared lib installed system wide, that should work. If not, you'll get an error about not being able to find the libphobos2.so.whatever.version. In that case, just point the path:
LD_LIBRARY_PATH=/path/to/dmd2/linux/lib64 ruby ./d.rb
More Convenient Version
You might want to make it a bit more automatic for the Ruby user. You can do that by calling rt_init
in the include file and doing an at_exit
for the term.
Create "i.d":
import std.stdio;
import std.conv;
extern(C)
void hello(const char* name)
{
// remember, it is a C function, so use C string
// and convert inside
writeln("hi from D, ", to!string(name));
}
Create "d.rb":
require 'rubygems'
require 'ffi'
module DInterface
extend FFI::Library
ffi_lib './i.so'
attach_function :rt_init, :rt_init, [], :int
attach_function :rt_term, :rt_term, [], :int
# now taking a string
attach_function :hello, :hello, [:string], :void
end
# call init right here for the user
DInterface::rt_init
# terminate automatically
at_exit do
DInterface::rt_term
end
Create "user.rb":
require './d'
DInterface::hello 'Ruby user!'
Compile and run (Linux 64-bit version):
dmd -shared -m64 -fPIC -defaultlib=libphobos2.so i.d
LD_LIBRARY_PATH=~/d/dmd2/linux/lib64 ruby ./user.rb