Project

go_gem

0.0
The project is in a healthy, maintained state
Helpers for compiling Go extensions for ruby
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

go-gem-wrapper

go-gem-wrapper is a wrapper for creating Ruby native extension in Go

GitHub Tag build Coverage Status Go Report Card Go Reference

Overview

Directory Name API Reference
/ github.com/ruby-go-gem/go-gem-wrapper (Go module) https://pkg.go.dev/github.com/ruby-go-gem/go-gem-wrapper
/_gem/ go_gem (Ruby gem) https://ruby-go-gem.github.io/go-gem-wrapper/

Requirements

  • Go 1.23+
  • Ruby 3.3+

Getting started

At first, patch to make a gem into a Go gem right after bundle gem

See _tools/patch_for_go_gem/

Please also add the following depending on the CI you are using.

GitHub Actions

e.g.

- uses: actions/setup-go@v5
  with:
    go-version-file: ext/GEM_NAME/go.mod

Implementing Ruby methods in Go

For example, consider the following Ruby method implemented in Go

module Example
  def self.sum(a, b)
    a + b
  end
end

1. Implementing function in Go

// ext/GEM_NAME/GEM_NAME.go

//export rb_example_sum
func rb_example_sum(_ C.VALUE, a C.VALUE, b C.VALUE) C.VALUE {
	aLong := ruby.NUM2LONG(ruby.VALUE(a))
	bLong := ruby.NUM2LONG(ruby.VALUE(b))

	sum := aLong + bLong

	return C.VALUE(ruby.LONG2NUM(sum))
}

2. Write C function definitions for Go functions

// ext/GEM_NAME/GEM_NAME.go

/*
#include "example.h"

// TODO: Append this
VALUE rb_example_sum(VALUE self, VALUE a, VALUE b);
*/
import "C"

3. Call exported C functions with the Init function

// ext/GEM_NAME/GEM_NAME.go

//export Init_example
func Init_example() {
	rb_mExample := ruby.RbDefineModule("Example")

	// TODO: Append this
	ruby.RbDefineSingletonMethod(rb_mExample, "sum", C.rb_example_sum, 2)
}

More examples

See also

Coverage

We provide auto-generated bindings for (almost) all CRuby functions available when including ruby.h 💪

See below for details.

Specification

Method name mapping from CRuby to Go

CRuby methods are mapped to Go methods based on the following rules

  • No lowercase letters included (/^[A-Z0-9_]+$/)
    • No changes
    • e.g. RB_NUM2UINT (CRuby) -> ruby.RB_NUM2UINT (Go)
  • Lowercase letters included
    • Converted to CamelCase
    • e.g. rb_define_method (CRuby) -> ruby.RbDefineMethod (Go)

Limitation

Most of the methods defined in ruby.h are automatically generated and defined in ruby/function_generated.go.

However, some of the methods listed below are not supported.

  1. deprecated or internal methods
  2. Methods with variable-length arguments
    • Because Go's variable-length arguments couldn't be passed directly to C.
    • However, it is possible to execute functions with variable length arguments in CRuby from Go with a hack like RbRaise in ruby/ruby_internal_error.go

Developing

Build

Run bundle exec rake ruby:example:build.

See bundle exec rake -T for more tasks.

See godoc in local

go install golang.org/x/tools/cmd/godoc@latest
godoc

open http://localhost:6060/pkg/github.com/ruby-go-gem/go-gem-wrapper/ruby/

Original idea

Ruby meets Go - RubyKaigi 2015