Difference between revisions of "Call D from Ruby using FFI"
(Created page with "Adam Ruppe posted this example in the [http://forum.dlang.org/post/fatqnbivseurruxsxsoh@forum.dlang.org Learn Forum]. The goal is to write a function in D and call it from Rub...") |
m (Category:HowTo) |
||
(2 intermediate revisions by one other user not shown) | |||
Line 5: | Line 5: | ||
Create the file "i.d" containing | Create the file "i.d" containing | ||
− | + | <syntaxhighlight lang="d"> | |
− | + | import std.stdio; | |
− | + | ||
− | + | extern(C) | |
− | + | void hello() | |
− | + | { | |
+ | writeln("hi from D"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
Compile it as a shared library. For example, to compile as a 64-bit shared library on Linux, you can do | Compile it as a shared library. For example, to compile as a 64-bit shared library on Linux, you can do | ||
− | + | <syntaxhighlight lang="bash"> | |
+ | dmd -shared -m64 -fPIC -defaultlib=libphobos2.so i.d | ||
+ | </syntaxhighlight> | ||
Create the file "d.rb" containing | Create the file "d.rb" containing | ||
+ | <syntaxhighlight lang="ruby"> | ||
require 'rubygems' | require 'rubygems' | ||
require 'ffi' | require 'ffi' | ||
Line 37: | Line 43: | ||
# terminate | # terminate | ||
DInterface::rt_term | DInterface::rt_term | ||
+ | </syntaxhighlight> | ||
Run the Ruby file: | Run the Ruby file: | ||
− | + | <syntaxhighlight lang="bash"> | |
+ | ruby ./d.rb | ||
+ | </syntaxhighlight> | ||
You should see | You should see | ||
Line 48: | Line 57: | ||
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: | 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: | ||
− | + | <syntaxhighlight lang="bash"> | |
+ | LD_LIBRARY_PATH=/path/to/dmd2/linux/lib64 ruby ./d.rb | ||
+ | </syntaxhighlight> | ||
==More Convenient Version== | ==More Convenient Version== | ||
Line 56: | Line 67: | ||
Create "i.d": | Create "i.d": | ||
− | + | <syntaxhighlight lang="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)); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
Create "d.rb": | Create "d.rb": | ||
+ | <syntaxhighlight lang="ruby"> | ||
require 'rubygems' | require 'rubygems' | ||
require 'ffi' | require 'ffi' | ||
Line 87: | Line 102: | ||
DInterface::rt_term | DInterface::rt_term | ||
end | end | ||
+ | </syntaxhighlight> | ||
Create "user.rb": | Create "user.rb": | ||
+ | <syntaxhighlight lang="ruby"> | ||
require './d' | require './d' | ||
DInterface::hello 'Ruby user!' | DInterface::hello 'Ruby user!' | ||
+ | </syntaxhighlight> | ||
Compile and run (Linux 64-bit version): | Compile and run (Linux 64-bit version): | ||
− | + | <syntaxhighlight lang="bash"> | |
− | + | dmd -shared -m64 -fPIC -defaultlib=libphobos2.so i.d | |
+ | LD_LIBRARY_PATH=~/d/dmd2/linux/lib64 ruby ./user.rb | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | [[Category:HowTo]] |
Latest revision as of 13:24, 3 March 2018
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