Examples
Reference projects
Three published gems use ruby-bindgen and are good places to read working
configuration, layout, and CI when starting your own bindings project.
| Project | Format | Size | When to use as a reference |
|---|---|---|---|
| BitmapPlusPlus-ruby | Rice (C++) | ~1 file | Wrapping a small, header-only C++ library. The cleanest end-to-end gem layout (ext/, lib/, sig/, test/, docs/, CMakePresets.json). |
| proj4rb | FFI (C) | medium | Wrapping a C library via FFI rather than a compiled extension. Shows library loading, version pinning, and Ruby-side wrappers. |
| opencv-ruby | Rice (C++) | very large | Wrapping a large, complex C++ library that needs heavy customization, CUDA guards, and post-regeneration manual edits. |
For learning, start with BitmapPlusPlus-ruby for C++ or proj4rb for C. Read opencv-ruby later, as a study of how to scale the same approach to 1,000+ classes and 10,000+ method bindings.
Minimal config snippets
Minimal end-to-end examples for each output format.
Rice (C++)
rice-bindings.yaml:
project: sample_ext
input: ./include
output: ./ext/generated
format: Rice
match:
- "**/*.hpp"
clang:
args:
- -I./include
- -std=c++17
- -xc++
Run:
ruby-bindgen rice-bindings.yaml
Output:
- One *-rb.cpp and *-rb.hpp per header
- Optional *-rb.ipp files when template _instantiate functions are generated
- Project files when project is set (sample_ext-rb.cpp, sample_ext-rb.hpp)
FFI (C)
ffi-bindings.yaml:
project: mylib
input: ./include
output: ./lib/generated
format: FFI
match:
- "**/*.h"
library_names:
- mylib
library_versions:
- "2"
- "1"
clang:
args:
- -I./include
- -xc
Run:
ruby-bindgen ffi-bindings.yaml
Output:
- A project loader file (mylib_ffi.rb) with require 'ffi', ffi_lib, and require_relative calls
- One Ruby content file per header with enums, structs, callbacks, and attach_function calls
CMake (for Rice output)
Important: CMake generation must run after Rice generation because it scans the output directory for *-rb.cpp files.
rice-bindings.yaml:
project: sample_ext
input: ./include
output: ./ext/generated
format: Rice
match:
- "**/*.hpp"
clang:
args:
- -I./include
- -std=c++17
- -xc++
cmake-bindings.yaml:
project: sample_ext
output: ./ext/generated
format: CMake
# input defaults to output for CMake and scans ./ext/generated for *-rb.cpp
include_dirs:
- "${CMAKE_CURRENT_SOURCE_DIR}/../include"
Run:
ruby-bindgen rice-bindings.yaml
ruby-bindgen cmake-bindings.yaml
Then build:
cd ./ext/generated
cmake --preset linux-debug
cmake --build build/linux-debug