Skip to content

Beginner Contributor Guide Ruby Extensions

Abinash Meher edited this page Jan 30, 2016 · 6 revisions

Beginner Contributor Guide - Ruby Extensions

To participate in developing ruby wrappers, you need to know basic C (for the c wrappers and Ruby C API) and basic Ruby (for writing the tests). We suggest you to go through the notebooks to have an understanding how the extension is used. You can also contribute if you don't have the knowledge of Ruby or Ruby C API. You should have a look at the Beginner Contributor Guide for C wrappers. We don't expect you to know the Ruby C API, for that you can always refer to the set of resources given below. I will explain in detail what you need to keep in mind while developing the Ruby wrappers (this will be specific to this project).

The general workflow while developing Ruby wrappers is as follows

  1. Wrap the feature/functions in C (in cwrapper.h and cwrapper.cpp)
  2. Write the tests for the c wrappers (in test_cwrapper.c)
  3. Write expected tests in Ruby with RSpec, specifying how do you want the feature/method to behave (in symengine.rb/spec)
  4. Write the source for the wrappers in Ruby C API/MRI, and make the tests pass. (in symengine.rb/ext/symengine)

The first two steps can be skipped if the C wrappers for that feature have already been developed and tested.

Background

Writing all the background knowledge here will be difficult. I strongly suggest to go through the Chapter Extending Ruby in Programming Ruby: The Pragmatic Programmers Guide. Also go through, README.EXT at least once before you proceed further. The Definitive Guide to Ruby's C API is also a nice place to learn from, after you have got a hang of it. Don't try to memorise the functions but rather see how the objects are handled, basically the life cycle of an object in Ruby C API.

Implementation

The extensions are packaged as a gem. The gem and the folder structure is in the symengine.rb repository. This is the gem directory. All the extensions go into the ext/symengine folder. Every class wrapped has a header file named as ruby_<class_name> (e.g. ruby_integer.h) and a source file ruby_<class_name>.c (e.g. ruby_integer.c).

All the class and module declarations are in symengine.h and the the most important function, Init_symengine() is in symengine.c. It is this function where all ruby classes and their methods have been declared.

We have the SymEngine module at the top level. And the classes are a part of it.

Naming Conventions

  • Modules are prefixed with m_
  • Classes are prefixed with c_
  • Class methods are named as c<class name in small>_<method_name>, e.g. cbasic_diff

Ruby C API Resources