ruby-bindgen generates bindings for C++ class templates, handling specializations, base class chains, and file organization automatically. For details on how Rice wraps class templates, see the Rice Class Templates documentation.
ruby-bindgen generates bindings for template class instantiations created via typedef or using statements:
template<typename T>
class Point
{
T x, y;
};
typedef Point<int> Point2i;
using Point2f = Point<float>;Generated bindings correctly handle:
- Fully qualified template arguments (
cv::Point<int>notPoint<int>) - Base class inheritance chains for templates
- Auto-generation of base class bindings when no typedef exists
Unqualified type names in template arguments are automatically qualified:
// Input: std::map<String, DictValue>::iterator
// Output: std::map<cv::String, cv::dnn::DictValue>::iteratorWhen a class inherits from a template instantiation, the base class binding is auto-generated if no typedef exists:
class PlaneWarper : public WarperBase<PlaneProjector>
{
};
// Auto-generates WarperBasePlaneProjector bindingFor template typedefs with base classes, the entire inheritance chain is resolved and generated in the correct order.
When a template typedef in one header inherits from a template defined in another header, ruby-bindgen will re-instantiate the ancestor chain in the derived file even if those ancestors were already instantiated in the base file. For example, if types.hpp has typedef Scalar_<double> Scalar and Scalar_ inherits from Vec<double, 4> which inherits from Matx<double, 4, 1>, the generated types-rb.cpp will include instantiation calls for all three — even though Vec4d and Matx41d were already emitted in matx-rb.cpp.
Rice handles this gracefully at runtime (re-registering an already-registered type is a no-op), so the duplicate instantiations are harmless but redundant. If this causes issues, you can remove the duplicate lines from the generated file by hand or use a refinement file to control instantiation order.
When a header contains class templates with specializations (via typedef or using), ruby-bindgen generates reusable _instantiate template functions. These are placed in a separate .ipp file to enable reuse without duplicate symbol errors.
Example: For templates.hpp containing:
template<typename T>
class Matrix
{
...
};
typedef Matrix<float> Matrixf;ruby-bindgen generates:
templates-rb.ipp (template instantiate functions):
#include <templates.hpp>
#include "templates-rb.hpp"
using namespace Rice;
template<typename T>
inline Rice::Data_Type<Matrix<T>> Matrix_instantiate(Rice::Module parent, const char* name)
{
return Rice::define_class_under<Matrix<T>>(parent, name).
define_constructor(Constructor<Matrix<T>>()).
define_attr("data", &Matrix<T>::data);
}templates-rb.cpp (Init function only):
#include "templates-rb.ipp"
void Init_Templates()
{
Rice::Data_Type<Matrix<float>> rb_cMatrixf =
Matrix_instantiate<float>(Rice::Module(rb_cObject), "Matrixf");
}The .ipp separation enables refinement files to reuse _instantiate functions without causing duplicate Init_ symbol errors:
// mat_refinements.cpp - Custom extensions
#include "mat-rb.ipp" // Gets _instantiate functions, NOT Init_Core_Mat
void Init_Mat_Refinements()
{
Rice::Data_Type<cv::Mat_<double>> rb_cMat1d =
Mat__instantiate<double>(rb_mCv, "Mat1d");
}