Skip to content
jdleesmiller edited this page Dec 11, 2010 · 2 revisions

Building Ruby extensions with Rice can lead to lots of odd issues, confusing compiler errors, and possibly confusion as to what exactly is happening. This page is to help explain these situations and solutions.

If your question isn’t answered here, please send me (jameskilton) a message, or open an Issue.

Questions

Answers

STL Support

Rice does not currently have support for STL containers outside of std::string. This is something being worked on. If you really need to have Rice convert, say, a std::vector or std::map, you’ll need to write your own to_ruby / from_ruby templates for these types for now, like those in the following example. (See also below).


// Not an official example; there may be a better way. Tested in rice 1.4.0.
#include <rice/Object.hpp>
#include <rice/Data_Type.hpp>
#include <rice/Array.hpp>

template<>
std::vector<int> from_ruby<std::vector<int> >(Rice::Object x)
{
  Rice::Array a(x);
  std::vector<int> result;
  result.reserve(a.size());
  for (Rice::Array::iterator it = a.begin(); it != a.end(); ++it) {
    result.push_back(from_ruby<int>(*it));
  }
  return result;
}

template<>
Rice::Object to_ruby<std::vector<int> >(std::vector<int> const & x)
{
  return Rice::Array(x.begin(), x.end());
}

Note that it’s not possible to write a method template<T> std::vector<T> from_ruby<std::vector<T> >(Rice::Object x), because that would be partial specialisation of a function template. We can, however, partially specialize the structs in Rice::detail, as follows. See this article for more explanation (esp. moral #2 and example 4).


// Not an official example; there may be a better way. Tested in rice 1.4.0.
namespace Rice {
  namespace detail {
    template<typename T>
    struct from_ruby_<std::vector<T> > 
    {
      typedef std::vector<T> Retval_T;

      static std::vector<T> convert(Rice::Object x) {
        Rice::Array a(x);
        std::vector<T> result;
        result.reserve(a.size());
        for (Rice::Array::iterator it = a.begin(); it != a.end(); ++it) {
          result.push_back(from_ruby<T>(*it));
        }
        return result;
      }
    };

    template<typename T>
    struct to_ruby_<std::vector<T> > 
    {
      static Rice::Object convert(std::vector<T> const & x) {
        return Rice::Array(x.begin(), x.end());
      }
    };
  }
}

Missing to_ruby / from_ruby errors

One of Rice’s biggest strengths is the automatic conversion of C++ types to Ruby types, and vice versa. This is handled through two simple templated methods:


template<typename T>
T from_ruby(Rice::Object x);
  
template<typename T>
Rice::Object to_ruby(T const & x);

In most cases, Rice will have definitions of these methods made for wrapped types, and things will progress smoothly. However, in cases where a given method uses a type that’s not wrapped by Rice elsewhere, or the type is being used in a special way that Rice needs to be told about, you’ll need to write our own version of these methods to tell Rice just how to do the C++ <=> Ruby conversions.

Clone this wiki locally