ruby-bindgen 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/LICENSE +25 -0
  4. data/README.md +68 -0
  5. data/Rakefile +8 -0
  6. data/bin/ruby-bindgen +133 -0
  7. data/docs/architecture.md +238 -0
  8. data/docs/c/c_bindings.md +65 -0
  9. data/docs/c/constants.md +21 -0
  10. data/docs/c/customizing.md +19 -0
  11. data/docs/c/filtering.md +24 -0
  12. data/docs/c/getting_started.md +56 -0
  13. data/docs/c/library_loading.md +53 -0
  14. data/docs/c/output.md +96 -0
  15. data/docs/c/types.md +61 -0
  16. data/docs/c/version_guards.md +105 -0
  17. data/docs/cmake/cmake_bindings.md +19 -0
  18. data/docs/cmake/filtering.md +26 -0
  19. data/docs/cmake/getting_started.md +52 -0
  20. data/docs/cmake/output.md +110 -0
  21. data/docs/configuration.md +351 -0
  22. data/docs/contributing.md +68 -0
  23. data/docs/cpp/buffers.md +24 -0
  24. data/docs/cpp/classes.md +139 -0
  25. data/docs/cpp/cpp_bindings.md +29 -0
  26. data/docs/cpp/customizing.md +124 -0
  27. data/docs/cpp/enums.md +42 -0
  28. data/docs/cpp/filtering.md +35 -0
  29. data/docs/cpp/getting_started.md +80 -0
  30. data/docs/cpp/iterators.md +94 -0
  31. data/docs/cpp/operators.md +170 -0
  32. data/docs/cpp/output.md +125 -0
  33. data/docs/cpp/templates.md +114 -0
  34. data/docs/examples.md +133 -0
  35. data/docs/index.md +133 -0
  36. data/docs/prior_art.md +37 -0
  37. data/docs/troubleshooting.md +243 -0
  38. data/docs/type_spelling.md +200 -0
  39. data/docs/updating_bindings.md +55 -0
  40. data/docs/version_guards.md +69 -0
  41. data/lib/ruby-bindgen/config.rb +63 -0
  42. data/lib/ruby-bindgen/generators/cmake/cmake.rb +171 -0
  43. data/lib/ruby-bindgen/generators/cmake/directory.erb +29 -0
  44. data/lib/ruby-bindgen/generators/cmake/guard.rb +55 -0
  45. data/lib/ruby-bindgen/generators/cmake/presets.erb +232 -0
  46. data/lib/ruby-bindgen/generators/cmake/project.erb +89 -0
  47. data/lib/ruby-bindgen/generators/ffi/callback.erb +1 -0
  48. data/lib/ruby-bindgen/generators/ffi/constant.erb +1 -0
  49. data/lib/ruby-bindgen/generators/ffi/enum_constant_decl.erb +1 -0
  50. data/lib/ruby-bindgen/generators/ffi/enum_decl.erb +4 -0
  51. data/lib/ruby-bindgen/generators/ffi/enum_decl_anonymous.erb +4 -0
  52. data/lib/ruby-bindgen/generators/ffi/ffi.rb +687 -0
  53. data/lib/ruby-bindgen/generators/ffi/field_decl.erb +1 -0
  54. data/lib/ruby-bindgen/generators/ffi/function.erb +5 -0
  55. data/lib/ruby-bindgen/generators/ffi/library.erb +39 -0
  56. data/lib/ruby-bindgen/generators/ffi/project.erb +18 -0
  57. data/lib/ruby-bindgen/generators/ffi/struct.erb +6 -0
  58. data/lib/ruby-bindgen/generators/ffi/translation_unit.erb +9 -0
  59. data/lib/ruby-bindgen/generators/ffi/typedef_decl.erb +1 -0
  60. data/lib/ruby-bindgen/generators/ffi/union.erb +6 -0
  61. data/lib/ruby-bindgen/generators/ffi/variable.erb +1 -0
  62. data/lib/ruby-bindgen/generators/ffi/version.erb +9 -0
  63. data/lib/ruby-bindgen/generators/ffi/version_method.erb +5 -0
  64. data/lib/ruby-bindgen/generators/generator.rb +52 -0
  65. data/lib/ruby-bindgen/generators/rice/auto_generated_base_class.erb +5 -0
  66. data/lib/ruby-bindgen/generators/rice/class.erb +31 -0
  67. data/lib/ruby-bindgen/generators/rice/class_template.erb +9 -0
  68. data/lib/ruby-bindgen/generators/rice/class_template_specialization.erb +10 -0
  69. data/lib/ruby-bindgen/generators/rice/constant.erb +9 -0
  70. data/lib/ruby-bindgen/generators/rice/constructor.erb +1 -0
  71. data/lib/ruby-bindgen/generators/rice/conversion_function.erb +4 -0
  72. data/lib/ruby-bindgen/generators/rice/cxx_iterator_method.erb +1 -0
  73. data/lib/ruby-bindgen/generators/rice/cxx_method.erb +6 -0
  74. data/lib/ruby-bindgen/generators/rice/enum_constant_decl.erb +7 -0
  75. data/lib/ruby-bindgen/generators/rice/enum_decl.erb +6 -0
  76. data/lib/ruby-bindgen/generators/rice/field_decl.erb +8 -0
  77. data/lib/ruby-bindgen/generators/rice/function.erb +6 -0
  78. data/lib/ruby-bindgen/generators/rice/function_pointer.rb +68 -0
  79. data/lib/ruby-bindgen/generators/rice/incomplete_class.erb +3 -0
  80. data/lib/ruby-bindgen/generators/rice/iterator_alias.erb +1 -0
  81. data/lib/ruby-bindgen/generators/rice/iterator_collector.rb +159 -0
  82. data/lib/ruby-bindgen/generators/rice/namespace.erb +5 -0
  83. data/lib/ruby-bindgen/generators/rice/non_member_operator_binary.erb +4 -0
  84. data/lib/ruby-bindgen/generators/rice/non_member_operator_inspect.erb +6 -0
  85. data/lib/ruby-bindgen/generators/rice/non_member_operator_unary.erb +4 -0
  86. data/lib/ruby-bindgen/generators/rice/operator[].erb +4 -0
  87. data/lib/ruby-bindgen/generators/rice/project.cpp.erb +18 -0
  88. data/lib/ruby-bindgen/generators/rice/project.hpp.erb +13 -0
  89. data/lib/ruby-bindgen/generators/rice/reference_qualifier.rb +495 -0
  90. data/lib/ruby-bindgen/generators/rice/rice.rb +1724 -0
  91. data/lib/ruby-bindgen/generators/rice/rice_include.hpp.erb +7 -0
  92. data/lib/ruby-bindgen/generators/rice/signature_builder.rb +230 -0
  93. data/lib/ruby-bindgen/generators/rice/template_resolver.rb +585 -0
  94. data/lib/ruby-bindgen/generators/rice/translation_unit.cpp.erb +40 -0
  95. data/lib/ruby-bindgen/generators/rice/translation_unit.hpp.erb +7 -0
  96. data/lib/ruby-bindgen/generators/rice/translation_unit.ipp.erb +3 -0
  97. data/lib/ruby-bindgen/generators/rice/type_index.rb +117 -0
  98. data/lib/ruby-bindgen/generators/rice/type_speller.rb +509 -0
  99. data/lib/ruby-bindgen/generators/rice/union.erb +5 -0
  100. data/lib/ruby-bindgen/generators/rice/variable.erb +5 -0
  101. data/lib/ruby-bindgen/inputter.rb +54 -0
  102. data/lib/ruby-bindgen/name_mapper.rb +65 -0
  103. data/lib/ruby-bindgen/namer.rb +138 -0
  104. data/lib/ruby-bindgen/outputter.rb +40 -0
  105. data/lib/ruby-bindgen/parser.rb +82 -0
  106. data/lib/ruby-bindgen/refinements/cursor.rb +57 -0
  107. data/lib/ruby-bindgen/refinements/string.rb +41 -0
  108. data/lib/ruby-bindgen/symbol_candidates.rb +282 -0
  109. data/lib/ruby-bindgen/symbol_entry.rb +21 -0
  110. data/lib/ruby-bindgen/symbols.rb +107 -0
  111. data/lib/ruby-bindgen/type_pointer_formatter.rb +35 -0
  112. data/lib/ruby-bindgen/version.rb +3 -0
  113. data/lib/ruby-bindgen.rb +19 -0
  114. data/ruby-bindgen.gemspec +52 -0
  115. metadata +260 -0
@@ -0,0 +1,351 @@
1
+ # Configuration
2
+
3
+ `ruby-bindgen` uses a YAML configuration file to specify how bindings should be generated. This approach keeps your build configuration versioned and reproducible.
4
+
5
+ ```bash
6
+ ruby-bindgen rice-bindings.yaml
7
+ ```
8
+
9
+ For end-to-end examples, see [C Bindings](c/c_bindings.md), [C++ Bindings](cpp/cpp_bindings.md), and [CMake Bindings](cmake/cmake_bindings.md).
10
+
11
+ ## Required Options
12
+
13
+ | Option | Description |
14
+ |----------|-------------------------------------------------------------------------------------------------------------------|
15
+ | `input` | Directory containing the header files to parse. Required for `FFI` and `Rice`. For `CMake`, if omitted it defaults to `output` so the generator scans previously generated `*-rb.cpp` files. Can be absolute or relative to the config file location. |
16
+ | `output` | Directory where generated binding files will be written. Can be absolute or relative to the config file location. |
17
+ | `format` | Type of bindings to generate: `Rice` for C++, `FFI` for C, or `CMake` for CMakeLists.txt. |
18
+
19
+ Relative paths for `input` and `output` are resolved from the config file's directory, not the current working directory. This makes configs portable across different machines.
20
+
21
+ ## Common Options
22
+
23
+ These options apply to all formats.
24
+
25
+ | Option | Default | Description |
26
+ |-----------------|--------------------|-------------------------------------------------------------------------------------------|
27
+ | `match` | `["**/*.{h,hpp}"]` for `FFI`/`Rice`, `["**/*-rb.cpp"]` for `CMake` | Array of glob patterns specifying which files to process. **Note:** removing a header from `match` does not delete its previously generated `*-rb.cpp` file. You must manually delete stale output files when removing headers. Auto-cleanup is not performed because `match` is often temporarily narrowed to regenerate a single file. |
28
+ | `skip` | `[]` | Array of glob patterns specifying which files to skip. For Rice/FFI, these match header file paths. For CMake, these match generated `*-rb.cpp` file paths. In most cases, it's better to add skips to the Rice/FFI config so the files are never generated, rather than skipping them in CMake after the fact. |
29
+ | `symbols` | `{}` | Symbol actions and name mappings grouped by type. See [Symbols](#symbols). |
30
+ | `export_macros` | `[]` | List of macros that indicate a function is exported. See [Export Macros](#export-macros). |
31
+ | `version_check` | none | Identifier used for version guards. Required when `symbols.versions` is non-empty. For **Rice**, this is a C preprocessor macro — symbols are wrapped in `#if version_check >= version` / `#endif`. For **FFI**, this is a Ruby method name — symbols are wrapped in `if version_check >= version` / `end`. See [Versions](#versions). |
32
+
33
+ ## C (FFI) Options
34
+
35
+ | Option | Default | Description |
36
+ |--------------------|----------|-------------|
37
+ | `project` | **required** | Project name. Used for the loader file name (`{project}_ffi.rb`) which contains the library preamble and `require_relative`s for each content file. |
38
+ | `library_names` | `[]` | Base names of shared libraries to load (e.g., `["proj"]` for `libproj`). |
39
+ | `library_versions` | `[]` | Library version suffixes to search for (e.g., `["25", "9"]`). Combined with `library_names` to build platform-specific search names like `libproj.so.25`. |
40
+ | `module` | filename | Ruby module name for the generated bindings. Defaults to the header filename camelized (e.g., `proj.h` → `Proj`). For the project loader, defaults to `project` camelized. Supports nested modules with `::` (e.g., `Proj::Api`). |
41
+ | `library_search_path` | none | Name of an environment variable containing a directory path. When the env var is set at runtime, library names are searched in that directory first before falling back to standard search. For example, `library_search_path: PROJ_LIB_PATH` generates code that checks `ENV['PROJ_LIB_PATH']` and prepends that path to each library name. |
42
+
43
+ ## C++ (Rice) Options
44
+
45
+ | Option | Default | Description |
46
+ |-----------------|----------------|-------------|
47
+ | `project` | none | Project name for the Ruby extension. Used for the `Init_` function name and project wrapper file names. Must be a valid C/C++ identifier. When provided, generates project wrapper files (`{project}-rb.cpp`, `{project}-rb.hpp`). When omitted, only per-file bindings are generated. |
48
+ | `include` | auto-generated | Path to a custom Rice include header. See [Include Header](cpp/output.md#include-header). |
49
+
50
+ ## CMake Options
51
+
52
+ | Option | Default | Description |
53
+ |----------------|---------|-------------|
54
+ | `project` | none | Project name used in the CMake `project()` command and build target name. When provided, generates the root `CMakeLists.txt` (with project setup, Rice fetch, Ruby detection) and `CMakePresets.json`. When omitted, only subdirectory `CMakeLists.txt` files are generated — useful when you manage the root project files yourself. |
55
+ | `include_dirs` | `[]` | List of include directory expressions added via `target_include_directories`. These are CMake expressions written directly into `CMakeLists.txt` (e.g., `${CMAKE_CURRENT_SOURCE_DIR}/../headers`). |
56
+ | `guards` | `{}` | Map of raw CMake condition expressions to arrays of generated path patterns. Matching directories are emitted inside guarded `add_subdirectory(...)` blocks; matching `*-rb.cpp` files are emitted inside guarded `target_sources(...)` blocks. Exact paths and globs are both supported. |
57
+
58
+ ## Compiler Toolchain
59
+
60
+ `ruby-bindgen` uses top-level toolchain keys to configure compiler settings for different platforms:
61
+
62
+ - **`clang-cl:`** - Used when `RUBY_PLATFORM` contains `mswin` (MSVC toolchain)
63
+ - **`clang:`** - Used on Linux, macOS, and MinGW
64
+
65
+ | Option | Default | Description |
66
+ |------------|-------------|-------------|
67
+ | `libclang` | auto-detect | Path to the libclang shared library. Nested under `clang-cl:` or `clang:`. When specified, sets the `LIBCLANG` environment variable before loading ffi-clang. |
68
+ | `args` | `[]` | Arguments passed to libclang for parsing (include paths, language standard, defines, etc.). Nested under `clang-cl:` or `clang:`. |
69
+
70
+ You only need to include the toolchain sections for platforms you target.
71
+
72
+ ### Resolution Flow
73
+
74
+ ```mermaid
75
+ flowchart TD
76
+ A["config.yaml location"] --> B["Resolve relative input/output paths"]
77
+ B --> C{"RUBY_PLATFORM contains mswin?"}
78
+ C -->|Yes| D["Use clang-cl section"]
79
+ C -->|No| E["Use clang section (Linux, macOS, MinGW)"]
80
+ D --> F["Set LIBCLANG from toolchain libclang (if provided)"]
81
+ E --> F
82
+ F --> G["Pass toolchain args to libclang parser"]
83
+ ```
84
+
85
+ ### Clang Arguments
86
+
87
+ The `args` section under each toolchain is crucial for successful parsing. You typically need:
88
+
89
+ 1. **System include paths** - Standard library headers
90
+ 2. **Library include paths** - The library's own headers
91
+ 3. **Language specification** - `-xc++` for C++ headers, `-xc` for C headers
92
+ 4. **Language standard** - `-std=c++17` or similar
93
+
94
+ #### Finding System Include Paths
95
+
96
+ On Linux/macOS:
97
+ ```bash
98
+ clang++ -E -x c++ - -v < /dev/null 2>&1 | grep "^ /"
99
+ ```
100
+
101
+ On Windows with MSVC:
102
+ - Visual Studio include paths (e.g., `C:\Program Files\Microsoft Visual Studio\...\include`)
103
+ - Windows SDK include paths (e.g., `C:\Program Files (x86)\Windows Kits\10\Include\...`)
104
+ - LLVM/Clang include paths if using clang
105
+
106
+ ### Finding Libclang
107
+
108
+ On Linux:
109
+ ```bash
110
+ # Common locations
111
+ /usr/lib64/libclang.so # Fedora, RHEL
112
+ /usr/lib/x86_64-linux-gnu/libclang-*.so # Debian, Ubuntu
113
+ /usr/lib/llvm-*/lib/libclang.so # Multiple LLVM versions
114
+
115
+ # Find all libclang installations
116
+ find /usr -name "libclang*.so" 2>/dev/null
117
+ ```
118
+
119
+ On macOS:
120
+ ```bash
121
+ # Homebrew LLVM
122
+ /opt/homebrew/opt/llvm/lib/libclang.dylib # Apple Silicon
123
+ /usr/local/opt/llvm/lib/libclang.dylib # Intel
124
+
125
+ # Xcode Command Line Tools
126
+ /Library/Developer/CommandLineTools/usr/lib/libclang.dylib
127
+ ```
128
+
129
+ On Windows:
130
+ ```
131
+ # Visual Studio bundled LLVM
132
+ C:\Program Files\Microsoft Visual Studio\2022\...\VC\Tools\Llvm\x64\bin\libclang.dll
133
+
134
+ # Standalone LLVM installation
135
+ C:\Program Files\LLVM\bin\libclang.dll
136
+ ```
137
+
138
+ ## Symbols
139
+
140
+ The `symbols` option groups per-symbol actions and name mappings by type. The action groups are `skip`, `versions`, and `overrides`. Name mappings use `rename_types` and `rename_methods`.
141
+
142
+ ### Skip
143
+
144
+ The `skip` key lists symbols to exclude from bindings. This works for functions, classes, enums, typedefs, unions, and variables. This is useful when:
145
+
146
+ - Symbols have export macros but still aren't available (build configuration issues)
147
+ - Symbols are internal/private APIs not meant for external use
148
+ - Symbols cause linker errors due to missing definitions
149
+
150
+ Symbol names support:
151
+
152
+ - Simple names: `versionMajor` - skips all symbols with this name
153
+ - Fully qualified names: `cv::ocl::PlatformInfo::versionMajor` - skips only that specific symbol
154
+ - Signatures: `cv::Mat_::zeros(int, const int *)` - skips only the overload with matching parameter types
155
+ - Regex patterns: `/pattern/` - skips symbols matching the regex
156
+
157
+ #### How Matching Works
158
+
159
+ For exact symbol matching, `ruby-bindgen` does not rely on just one spelling. It tries a small set of candidate names so that configuration can match what users usually write in headers.
160
+
161
+ For a member function such as `cv::dnn::Layer::init`, the candidate set typically includes:
162
+
163
+ - The simple spelling: `init`
164
+ - The semantic qualified name from libclang: `cv::dnn::dnn4_v20241223::Layer::init`
165
+ - A parent-type form that collapses inline namespaces: `cv::dnn::Layer::init`
166
+
167
+ For overloads, the same shapes are also tried with parameter lists appended:
168
+
169
+ - `init(const cv::Mat &)`
170
+ - `cv::dnn::dnn4_v20241223::Layer::init(const cv::Mat &)`
171
+ - `cv::dnn::Layer::init(const cv::Mat &)`
172
+
173
+ This matters for libraries such as OpenCV, where public APIs are often declared inside versioned inline namespaces but users usually write the enclosing API name in configuration.
174
+
175
+ Two additional normalizations are worth knowing:
176
+
177
+ - Anonymous scopes are stripped from user-facing matches. For example, an enum constant reported by clang as `Outer::(unnamed enum at ... )::Value` can be matched as `Outer::Value`.
178
+ - Macros only match by their simple name, because libclang does not provide a usable qualified name for macro definitions.
179
+
180
+ ```yaml
181
+ symbols:
182
+ skip:
183
+ - versionMajor # Skips all symbols named "versionMajor"
184
+ - cv::ocl::PlatformInfo::versionMinor # Skips only this specific method
185
+ - "cv::Mat_::zeros(int, const int *)" # Skips only this overload (others remain)
186
+ - /cv::dnn::.*Layer::init.*/ # Regex: skips all init* methods on any Layer class
187
+ - DeprecatedEnum # Skips an enum
188
+ - InternalUnion # Skips a union
189
+ - debugVariable # Skips a variable
190
+ ```
191
+
192
+ ### Versions
193
+
194
+ The `versions` key wraps symbols in version guards. Each sub-key is the minimum version value, with a list of symbol names underneath.
195
+
196
+ For **Rice** (C++), this requires the `version_check` option to be set. The generator wraps version-specific symbols in `#if version_check >= version` / `#endif` preprocessor directives.
197
+
198
+ ```yaml
199
+ format: Rice
200
+ version_check: CV_VERSION
201
+ symbols:
202
+ versions:
203
+ 40100:
204
+ - cv::Foo::baz
205
+ 40500:
206
+ - /cv::cuda::.*/
207
+ ```
208
+
209
+ This generates:
210
+ ```cpp
211
+ #if CV_VERSION >= 40100
212
+ .define_method("baz", &cv::Foo::baz)
213
+ #endif
214
+ ```
215
+
216
+ For **FFI** (C), this requires the `version_check` option to be set to a Ruby method name. The generator wraps version-specific symbols in `if version_check >= version` Ruby conditionals and generates a `{project}_version.rb` skeleton file. The user implements the version detection method — typically by calling the library's own version API. See [Version Detection](c/version_guards.md) for a full example.
217
+
218
+ ```yaml
219
+ format: FFI
220
+ project: proj
221
+ version_check: proj_version
222
+ symbols:
223
+ skip:
224
+ - PJ_INFO # manually defined in version file
225
+ - proj_info # manually defined in version file
226
+ versions:
227
+ 60100:
228
+ - proj_normalize_for_visualization
229
+ 60200:
230
+ - proj_cleanup
231
+ ```
232
+
233
+ This generates:
234
+ ```ruby
235
+ if proj_version >= 60100
236
+ attach_function :proj_normalize_for_visualization, ...
237
+ end
238
+ ```
239
+
240
+ See [Version Guards](version_guards.md) for the Rice guide and [Version Detection](c/version_guards.md) for a full FFI example.
241
+
242
+ ### Overrides (FFI only)
243
+
244
+ The `overrides` key replaces the generated `attach_function` signature for specific functions. This is useful when ruby-bindgen's type heuristics produce the wrong FFI type — for example, C functions that return `int` 0/1 for boolean, or use `size_t` parameters that resolve to `:ulong`.
245
+
246
+ Each entry maps a C function name to a signature string that replaces everything after `attach_function :ruby_name, :c_name, `:
247
+
248
+ ```yaml
249
+ symbols:
250
+ overrides:
251
+ # C returns int 0/1, but Ruby 0 is truthy so must use :bool
252
+ proj_is_crs: "[:pointer], :bool"
253
+ # size_t vs ulong: on 64-bit Windows size_t is 8 bytes but ulong is 4 bytes
254
+ proj_trans_generic: "[:pointer, PjDirection, :pointer, :size_t, :size_t, ...], :size_t"
255
+ # Output buffer: char *s is caller-allocated, return is same pointer
256
+ proj_rtodms2: "[:pointer, :ulong, :double, :int, :int], :pointer"
257
+ ```
258
+
259
+ ### Overload-Specific Skipping
260
+
261
+ When a function has multiple overloads but only some cause problems (e.g., linker errors), you can target a specific overload by appending its parameter types in parentheses:
262
+
263
+ ```yaml
264
+ symbols:
265
+ skip:
266
+ - cv::Mat_::zeros # Skips ALL overloads of zeros
267
+ - "cv::Mat_::zeros(int, const int *)" # Skips only zeros(int ndims, const int* sz)
268
+ ```
269
+
270
+ The parameter types must match the canonical clang type spelling exactly (e.g., `const int *` not `const int*` or `int const *`).
271
+
272
+ ### Regex Patterns
273
+
274
+ Regex patterns are enclosed in forward slashes (`/pattern/`) and are matched against the same candidate set as exact names: simple names, semantic qualified names, and inline-namespace-collapsed member names when available. This is particularly useful for:
275
+
276
+ - Matching across versioned inline namespaces (e.g., `cv::dnn::dnn4_v20241223::Layer`)
277
+ - Skipping families of related methods
278
+ - Handling template specializations
279
+
280
+ `ruby-bindgen` automatically skips:
281
+
282
+ - Deprecated functions (marked with `__attribute__((deprecated))`)
283
+ - Methods returning pointers to incomplete types (pimpl pattern)
284
+
285
+ ## Export Macros
286
+
287
+ The `export_macros` option filters functions based on the presence of specific macros in the source code. This is useful for libraries that use macros to control symbol visibility.
288
+
289
+ When specified, only functions whose source text contains at least one of the listed macros will be included in the bindings. This prevents linker errors from trying to wrap internal functions that aren't exported from the shared library.
290
+
291
+ ```yaml
292
+ export_macros:
293
+ - CV_EXPORTS
294
+ - CV_EXPORTS_W
295
+ ```
296
+
297
+ ### Common Library Macros
298
+
299
+ | Library | Export Macros |
300
+ |---------|--------------|
301
+ | OpenCV | `CV_EXPORTS`, `CV_EXPORTS_W`, `CV_EXPORTS_W_SIMPLE` |
302
+ | Qt | `Q_DECL_EXPORT`, `Q_CORE_EXPORT` |
303
+ | Boost | `BOOST_*_DECL` |
304
+
305
+ ### Name Mappings
306
+
307
+ ruby-bindgen applies heuristics to convert C++ names to Ruby names — for example, `isEnabled()` becomes `enabled?` and `operator()` becomes `call`. These heuristics sometimes guess wrong. The `rename_methods` and `rename_types` keys under `symbols` let you override the generated names without manual post-generation edits.
308
+
309
+ Both options use the same pattern syntax as `symbols` names: plain strings for exact match, `/pattern/` for regex.
310
+
311
+ #### Type Mappings
312
+
313
+ Override generated Ruby class names for template instantiations. Supports `\1`, `\2`, etc. capture group substitution in regex replacements.
314
+
315
+ ```yaml
316
+ symbols:
317
+ rename_types:
318
+ # OpenCV Matx naming convention: MatxUnsignedChar21 → Matx21b
319
+ - from: /^MatxUnsignedChar(\d+)$/
320
+ to: Matx\1b
321
+ - from: /^MatxUnsignedShort(\d+)$/
322
+ to: Matx\1w
323
+ - from: /^MatxShort(\d+)$/
324
+ to: Matx\1s
325
+ - from: /^MatxInt(\d+)$/
326
+ to: Matx\1i
327
+ ```
328
+
329
+ Without these overrides, `Matx<unsigned char, 2, 1>` would generate the Ruby class name `MatxUnsignedChar21`. With the mapping, it becomes `Matx21b`, matching OpenCV's naming convention.
330
+
331
+ #### Method Mappings
332
+
333
+ Override generated Ruby method names. The `from` field is a C++ name (simple or fully qualified), the `to` field is the desired Ruby name.
334
+
335
+ ```yaml
336
+ symbols:
337
+ rename_methods:
338
+ # Exact match by qualified name — grab is not a predicate, it grabs a frame
339
+ - from: cv::VideoCapture::grab
340
+ to: grab
341
+ # Override operator() → [] for element/ROI access
342
+ - from: cv::Mat::operator()
343
+ to: "[]"
344
+ - from: cv::UMat::operator()
345
+ to: "[]"
346
+ # Override operator() → to_size for MatSize (returns a Size, not element access)
347
+ - from: cv::MatSize::operator()
348
+ to: to_size
349
+ ```
350
+
351
+ Without these overrides, ruby-bindgen would generate `grab?` (bool return, no params triggers predicate heuristic) and `call` (default `operator()` mapping).
@@ -0,0 +1,68 @@
1
+ # Contributing
2
+
3
+ Guidelines for changing `ruby-bindgen` and its generated-output tests.
4
+
5
+ ## Key Files
6
+
7
+ - `lib/ruby-bindgen/generators/generator.rb` - base class shared by all generators
8
+ - `lib/ruby-bindgen/generators/rice/rice.rb` - main AST walker for Rice code generation
9
+ - `lib/ruby-bindgen/generators/rice/*.erb` - Rice templates
10
+ - `lib/ruby-bindgen/generators/ffi/ffi.rb` - main AST walker for FFI code generation
11
+ - `lib/ruby-bindgen/generators/cmake/cmake.rb` - CMake file generator
12
+ - `test/headers/cpp/*.hpp` - C++ input headers for tests
13
+ - `test/bindings/cpp/*-rb.cpp` - expected generated output (golden files)
14
+
15
+ ## Run Tests
16
+
17
+ Run all tests before updating expected files:
18
+
19
+ ```bash
20
+ bundle exec ruby -Ilib -Itest test/ffi_test.rb
21
+ bundle exec ruby -Ilib -Itest test/rice_test.rb
22
+ bundle exec ruby -Ilib -Itest test/cmake_test.rb
23
+ ```
24
+
25
+ Run one test:
26
+
27
+ ```bash
28
+ bundle exec ruby -Ilib -Itest test/rice_test.rb --name test_classes
29
+ ```
30
+
31
+ Important:
32
+ - Run `cmake_test` after `rice_test` because it scans generated `*-rb.cpp` files.
33
+
34
+ ## Updating Expected Files
35
+
36
+ Only update expected outputs after all tests pass on current expectations.
37
+
38
+ ```bash
39
+ UPDATE_EXPECTED=1 bundle exec ruby -Ilib -Itest test/rice_test.rb
40
+ UPDATE_EXPECTED=1 bundle exec ruby -Ilib -Itest test/cmake_test.rb
41
+ ```
42
+
43
+ ## Test Coverage Requirement
44
+
45
+ Every bug fix should include test coverage:
46
+
47
+ - Add or adjust headers in `test/headers/cpp/`
48
+ - Update expected generated outputs in `test/bindings/cpp/`
49
+
50
+ For cross-file typedef issues, use:
51
+ - `test/headers/cpp/cross_file_base.hpp`
52
+ - `test/headers/cpp/cross_file_derived.hpp`
53
+
54
+ ## Regenerating opencv-ruby Bindings
55
+
56
+ Use the project configs in:
57
+ - `<opencv-ruby>/ext/rice-bindings.yaml`
58
+ - `<opencv-ruby>/ext/cmake-bindings.yaml`
59
+
60
+ Generate with:
61
+
62
+ ```bash
63
+ cd <ruby-bindgen>
64
+ # 1. Generate Rice source files
65
+ bundle exec ruby -Ilib bin/ruby-bindgen <opencv-ruby>/ext/rice-bindings.yaml
66
+ # 2. Generate CMake files
67
+ bundle exec ruby -Ilib bin/ruby-bindgen <opencv-ruby>/ext/cmake-bindings.yaml
68
+ ```
@@ -0,0 +1,24 @@
1
+ # Buffers and Pointers
2
+
3
+ `ruby-bindgen` automatically wraps some pointer parameters and return types. For details on using buffers and pointers from Ruby, see the Rice documentation on [Buffers](https://ruby-rice.github.io/4.x/bindings/buffers/) and [Pointers](https://ruby-rice.github.io/4.x/bindings/pointers/).
4
+
5
+ Pointers to most fundamental types (`int*`, `double*`, `unsigned char*`, `void*`, etc.) and double pointers (`T**`) are automatically wrapped using Rice's `ArgBuffer` and `ReturnBuffer` classes:
6
+
7
+ ```cpp
8
+ void processData(int* data, int size); // ArgBuffer("data")
9
+ void getMinMax(double* min, double* max); // Out parameters via ArgBuffer
10
+ int* createBuffer(int size); // ReturnBuffer
11
+ void processArrays(float** matrices, int count); // Double pointer via ArgBuffer
12
+ ```
13
+
14
+ `char*` and `wchar_t*` are treated as strings rather than raw buffers, so they do **not** use `ArgBuffer` or `ReturnBuffer`:
15
+
16
+ ```cpp
17
+ void processCharBuffer(char* buffer, int length); // Arg("buffer")
18
+ ```
19
+
20
+ This distinction matters for APIs that mix byte buffers and strings:
21
+
22
+ - `unsigned char*` is treated as a byte buffer
23
+ - `char*` / `wchar_t*` are treated as string pointers
24
+ - Any `T**` is treated as a buffer-style pointer, even when `T` is a class type
@@ -0,0 +1,139 @@
1
+ # Classes & Structs
2
+
3
+ `ruby-bindgen` generates Rice bindings for C++ classes and structs, including constructors, methods, member variables, and single inheritance. For details on how Rice wraps classes, see the Rice documentation on [Classes](https://ruby-rice.github.io/4.x/bindings/classes/), [Constructors](https://ruby-rice.github.io/4.x/bindings/constructors/), [Methods](https://ruby-rice.github.io/4.x/bindings/methods/), [Overloaded Methods](https://ruby-rice.github.io/4.x/bindings/overloaded_methods/), [Attributes](https://ruby-rice.github.io/4.x/bindings/attributes/), and [Constants](https://ruby-rice.github.io/4.x/bindings/constants/).
4
+
5
+ ## Constructors
6
+
7
+ ### Multiple Constructors
8
+
9
+ All public, non-deleted, non-deprecated constructors are wrapped:
10
+
11
+ ```cpp
12
+ class MyClass {
13
+ MyClass();
14
+ MyClass(int x);
15
+ MyClass(int x, int y);
16
+ };
17
+ ```
18
+
19
+ ### Implicit Default Constructor
20
+
21
+ If a class has no explicit constructors, the implicit default constructor is wrapped.
22
+
23
+ ### Skipped Constructors
24
+
25
+ - Move constructors
26
+ - Deleted constructors
27
+ - Deprecated constructors
28
+ - Constructors of abstract classes
29
+
30
+ ## Attributes
31
+
32
+ ### Public Member Variables
33
+
34
+ Public member variables generate getter/setter methods via `define_attr`:
35
+
36
+ ```cpp
37
+ class Point {
38
+ public:
39
+ int x, y; // Generates x, x=, y, y=
40
+ };
41
+ ```
42
+
43
+ ### Static Member Variables
44
+
45
+ Static members on classes use `define_singleton_attr`.
46
+
47
+ ### Constants
48
+
49
+ `const` qualified variables and namespace-level variables generate Ruby constants.
50
+
51
+ ## Single Inheritance
52
+
53
+ ```cpp
54
+ class Derived : public Base {};
55
+ ```
56
+
57
+ Generates:
58
+ ```cpp
59
+ define_class<Derived, Base>("Derived")
60
+ ```
61
+
62
+ For template base class inheritance, see [Templates](templates.md#template-base-classes).
63
+
64
+ ## Methods
65
+
66
+ ### Overloaded Methods
67
+
68
+ Overloaded methods are automatically detected and generate explicit type signatures:
69
+
70
+ ```cpp
71
+ void process(int x);
72
+ void process(double x);
73
+ ```
74
+
75
+ Generates:
76
+ ```cpp
77
+ define_method<void(MyClass::*)(int)>("process", &MyClass::process, Arg("x")).
78
+ define_method<void(MyClass::*)(double)>("process", &MyClass::process, Arg("x"));
79
+ ```
80
+
81
+ ### Conversion Operators
82
+
83
+ Type conversion operators generate appropriately named Ruby methods:
84
+
85
+ ```cpp
86
+ operator bool() const; // to_bool
87
+ operator std::string() const; // to_s
88
+ operator int*(); // to_ptr (non-const)
89
+ operator const int*() const; // to_const_ptr
90
+ ```
91
+
92
+ Template parameter conversions in class templates use generic names (`to_ptr`, `to_const_ptr`) to avoid invalid method names.
93
+
94
+ For a complete table of conversion type mappings, see the [Operators](operators.md#conversion-operators) page.
95
+
96
+ ### Callbacks
97
+
98
+ `ruby-bindgen` understands C-style callbacks and generates the appropriate Rice [callback code](https://ruby-rice.github.io/4.x/bindings/callbacks/).
99
+
100
+ ### Safe Bool Idiom
101
+
102
+ Pre-C++11 "safe bool idiom" using typedef to member function pointer is automatically skipped:
103
+
104
+ ```cpp
105
+ typedef void (MyClass::*bool_type)() const;
106
+ operator bool_type() const; // Skipped
107
+ ```
108
+
109
+ ### Default Values
110
+
111
+ `ruby-bindgen` preserves C++ default parameter values, handling namespace qualification and type constraints.
112
+
113
+ Default values are automatically qualified with full namespace paths:
114
+
115
+ ```cpp
116
+ void func(int flags = NORM_L2); // -> cv::NORM_L2
117
+ void func(Mat m = noArray()); // -> cv::noArray()
118
+ void func(Scalar s = Scalar::all(0)); // -> cv::Scalar::all(0)
119
+ ```
120
+
121
+ Default values referencing class template members preserve template parameters:
122
+
123
+ ```cpp
124
+ template<typename T>
125
+ class Quat {
126
+ static constexpr T EPS = 1e-6;
127
+ Quat(T eps = EPS); // -> cv::Quat<T>::EPS
128
+ };
129
+ ```
130
+
131
+ Default parameter values are only generated for copyable types. `ruby-bindgen` detects non-copyable types via private copy constructors, deleted copy constructors (`= delete`), or inherited inaccessible copy constructors:
132
+
133
+ ```cpp
134
+ class NonCopyable {
135
+ NonCopyable(const NonCopyable&) = delete;
136
+ };
137
+
138
+ void func(NonCopyable nc = NonCopyable()); // Default value NOT generated
139
+ ```
@@ -0,0 +1,29 @@
1
+ # C++ Bindings
2
+
3
+ `ruby-bindgen` creates Ruby bindings for C++ libraries using [Rice](https://github.com/ruby-rice/rice). Creating C++ bindings takes more work than creating C bindings, so if a library provides both a C and C++ API you should use the C API.
4
+
5
+ `ruby-bindgen` does its best to generate compilable Rice code. It has been battle tested against [OpenCV](https://github.com/opencv/opencv), which is a large, complex C++ API with over a thousand classes and ten thousand methods.
6
+
7
+ For many libraries, the generated bindings will compile and work with no additional changes. For example, [BitmapPlusPlus-ruby](https://ruby-rice.github.io/BitmapPlusPlus-ruby/) is a fully automated set of bindings generated by `ruby-bindgen` for the BitmapPlusPlus library.
8
+
9
+ For more complex libraries, like [OpenCV](https://github.com/opencv/opencv), some [customization](customizing.md) will likely be required.
10
+
11
+ ## Getting Started
12
+
13
+ See [Getting Started](getting_started.md) for a step-by-step guide to creating your first Rice bindings.
14
+
15
+ ## Output
16
+
17
+ See [Rice Output](output.md) for details on the generated files, including header files, project files, the include header, and the init function call graph.
18
+
19
+ ## Build System
20
+
21
+ After generating Rice bindings, you will need to setup a build system for your extension. `ruby-bindgen` can generate [CMake build files](../cmake/cmake_bindings.md) to compile and link the generated bindings.
22
+
23
+ ## Packaging
24
+
25
+ For packaging your extension as a gem, see the Rice [Packaging](https://ruby-rice.github.io/4.x/packaging/packaging/) documentation.
26
+
27
+ ## Example
28
+
29
+ For a complete, fully automated example see [BitmapPlusPlus-ruby](https://ruby-rice.github.io/BitmapPlusPlus-ruby/).