This document describes internal conventions for contributors working on the
C extension in ext/duckdb/.
The C function must be named <classname>_<methodname>, where classname is
the lowercase file name (without .c) and methodname is the Ruby method name.
rb_define_method(cDuckDBDatabase, "close", database_close, 0); // OK
rb_define_method(cDuckDBDatabase, "close", duckdb_database_close, 0); // NG — looks like DuckDB C API
rb_define_method(cDuckDBDatabase, "close", rbduckdb_database_close, 0); // NG — rbduckdb_ is for externs onlyThe Ruby method name must start with _. The C function uses a double
underscore naturally: classname + _ separator + _methodname.
rb_define_private_method(cDuckDBDatabase, "_connect", database__connect, 0); // OK
rb_define_private_method(cDuckDBDatabase, "_connect", database_connect, 0); // NG — single underscore
rb_define_private_method(cDuckDBDatabase, "_connect", rbduckdb_database_connect, 0); // NG
rb_define_private_method(cDuckDBDatabase, "connect", database_connect, 0); // NG — Ruby name must start with '_'Note: private _initialize methods produce C function names like
foo__initialize. The double underscore is intentional and consistent with
this rule.
rb_define_private_method(cDuckDBFoo, "_initialize", foo__initialize, 2); // OK — double underscore is intentionalrb_define_alloc_func(cDuckDBDatabase, allocate); // OK
rb_define_alloc_func(cDuckDBDatabase, database_allocate); // NGstatic void deallocate(void *ctx) { ... } // OK
static void database_free(void *ctx) { ... } // NGstatic size_t memsize(const void *p) { ... } // OK
static size_t database_memsize(const void *p) { ... } // NGNo fixed naming rule, but the name must be meaningful and must not clash with
any DuckDB C API symbol. A verb_noun or classname_verb_noun pattern is
recommended for non-registered internal helpers.
Special Ruby method name characters map to C identifiers as follows:
| Ruby method | C function suffix | Example |
|---|---|---|
finished? |
finished_p |
pending_result_finished_p |
name= |
set_name |
scalar_function_set_name |
method! |
method_bang |
(if needed) |
Using set_ prefix for = setters avoids a naming conflict with a getter of
the same base name (e.g., name getter → foo_name, name= setter →
foo_set_name).
The s_ prefix distinguishes singleton (class) methods from instance methods.
rb_define_singleton_method(cDuckDBDatabase, "open", database_s_open, 1); // OKPublic Ruby methods registered via rb_define_method must not have a _ prefix
in their Ruby name. The _ prefix is reserved for the private-via-wrapper
pattern. If a method is private, use rb_define_private_method with a
_-prefixed name.
rb_define_method(cDuckDBFoo, "_internal_type", foo__internal_type, 0); // NG — public method with _ prefix
rb_define_private_method(cDuckDBFoo, "_internal_type", foo__internal_type, 0); // OKClass-init extern functions must not include a redundant duckdb_ segment.
void rbduckdb_init_database(void); // OK
void rbduckdb_init_duckdb_database(void); // NG — redundant duckdb_All functions with external linkage (declared in .h files, called from other
.c files) must start with rbduckdb_.
rubyDuckDB *rbduckdb_get_struct_database(VALUE obj); // OK
rubyDuckDB *duckdb_get_struct_database(VALUE obj); // NG — looks like DuckDB C API
rubyDuckDB *get_struct_database(VALUE obj); // NG — no namespace