std::vector#
Along with std::string
, std::vector
is a workhorse of many C++ code bases. Although there is a direct conceptual mapping between a std::vector
and a Ruby Array
, Rice does not copy a vector to an Array. Instead, it wraps std::vector
.
There are multiple reasons for this:
std::vector
instantiations can only contain one type, while Ruby Arrays can contain different typesstd::vector
instances can be quite largestd::vector
instances commonly contain C++ classes that have complex copy or move semanticshaving two disconnected copies of data, one in C++ and one in Ruby, is usually undesirable
Rice will automatically define Ruby classes for each instantiation of std::vector
it finds. You may also manually define Ruby classes via the use of define_vector
or define_vector_under
methods. But make sure to define them before Rice automatically creates them.
Example:
std::vector<std::string> makeStringVector()
{
return std::vector {"one", "two", "three"};
}
define_vector<std::vector<std::string>>("StringVector");
define_global_function("make_string_vector", &makeStringVector);
Once you have defined this Ruby class, you can create a new instance like this:
vector = StringVector.new
vector.push("value 1")
vector.push("value 2")
Array to Vector#
For C++ methods that take vector arguments, you can instantiate a new vector from Ruby (see Automatically Generated Ruby Classes).
For example, assume this C++ code:
void passVector(std::vector<int> ints)
{
}
define_vector<std::vector<std::int>("IntVector");
define_global_function("pass_vector", &passVector);
One way to call it from Ruby is like this:
vector = IntVector.new
vector.push(37)
pass_vector(vector)
In this case, Ruby is wrapping a C++ vector. Therefore any changes made to the vector in C++ will be visible to Ruby.
However, it is often more convenient to pass a Ruby array instead. This is especially true if you are using Rice’s automatic stl classes.
Therefore Rice also supports this usage:
array = [3, 5, 9]
pass_vector(array)
In this case, Rice will copy the Ruby array instead of wrapping it. Thus any modifications made in C++ will not be visible to Ruby.
Ruby API#
Rice tries to make std::vector
look like a Ruby Array by giving it an API that is a subset of Array
. However, there are differences you need to keep in mind.
First, the following methods only work if the vector type is copyable (copying is done in C++):
Vector#copy(other)
Vector#resize
Second, the following methods only work if the vector type implements C++’s equal operator, operator==
:
Vector#delete
Vector#include?
Vector#index
Third, if the vector type supports C++ streams, then the following method will work, otherwise it will return “Not Printable”
Vector#to_s