⬆️ ⬇️

Ruby Go shared library connections

With the release of Go 1.5, it is possible to make a go library for third-party programs in other languages. That is, you can write a package that does something interesting and hard or just a ready-made solution and connect it to another non-Go program. This may be C, android, objective C and etc. I will show how it can be easily connected to Ruby.



1. If you have a ready-made solution for a go problem, then why not write it again in Ruby;

2. Go is obviously faster than Ruby if we are talking about our logic and not ready-made solutions with gem in which C often works;

3. Go requires less memory if you need to work with a bunch of data.



Let's start with the Go package.



We write our fast good working solutions on Go:

Go Code
package main import "C" //export add func add(x, y int) int { c := 0 for i := 0; i < 50000; i++ { c += x + y + 1 } return c } func main() {} 




This should contain main. Be sure to specify:

 import "C" 


And for the function that will be available from the outside, you must specify:

 //export % % 


Now that the GO program is ready, you need to build it:

 go build -buildmode=c-shared -o libadd.so testruby.go 


-buildmode is what appeared on Go 1.5, there are several different options, we need c-shared. After compilation we get .so and .h file. Now it can be switched to non-GO programs.

')

Now part of ruby.



We need gem ffi . We install it via gem install or via gemfile + bundle install. We connect our library to Ruby:

Ruby Code
 require 'ffi' module MegaSum extend FFI::Library ffi_lib 'lib/libadd.so' attach_function :add, [:int, :int], :int end 




Here we indicate where our .so file is, what call functions it has (on which we wrote "// export"), what they accept and what they return (you can see the full list of types here ). After that you can work:

Call go
  def self.add_go(x,y) Sum.add(x,y) end 




The first call will be a little slow (probably loads everything into memory).



Benchmarks!

Ruby code that does the same
 def self.add_ruby(x,y) c = 0 i = 0 while i<50000 c += x + y + 1 i = i+1 end c end 




 [21] pry(main)> Benchmark.realtime { (1..1000).to_a.each {GoHello.add_ruby(3,2) }} => 1.763254 [22] pry(main)> Benchmark.realtime { (1..1000).to_a.each {GoHello.add_go(3,2) }} => 0.030442 [23] pry(main)> Benchmark.realtime { (1..100000).to_a.each {GoHello.add_go(3,2) }} => 3.103797 [24] pry(main)> Benchmark.realtime { (1..100000).to_a.each {GoHello.add_ruby(3,2) }} => 195.282368 


As you can see, in simple arithmetic, Go overtakes Ruby by 60 times.



Minuses:

1. I'm not sure that you can build a bunch of Gorutin in Go. It worked for me on a small check (not thousands of gorutin);



P.C .: There is a similar solution for Python here .

Source: https://habr.com/ru/post/266037/



All Articles