mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
2488 lines
86 KiB
Plaintext
2488 lines
86 KiB
Plaintext
# extension.rdoc - -*- RDoc -*- created at: Mon Aug 7 16:45:54 JST 1995
|
|
|
|
{日本語}[rdoc-ref:extension.ja.rdoc]
|
|
|
|
= Creating extension libraries for Ruby
|
|
|
|
This document explains how to make extension libraries for Ruby.
|
|
|
|
== Basic Knowledge
|
|
|
|
In C, variables have types and data do not have types. In contrast,
|
|
Ruby variables do not have a static type, and data themselves have
|
|
types, so data will need to be converted between the languages.
|
|
|
|
Objects in Ruby are represented by the C type +VALUE+. Each VALUE
|
|
data has its data type.
|
|
|
|
To retrieve C data from a VALUE, you need to:
|
|
|
|
1. Identify the VALUE's data type
|
|
2. Convert the VALUE into C data
|
|
|
|
Converting to the wrong data type may cause serious problems.
|
|
|
|
=== Ruby data types
|
|
|
|
The Ruby interpreter has the following data types:
|
|
|
|
+T_NIL+ :: +nil+
|
|
+T_OBJECT+ :: ordinary object
|
|
+T_CLASS+ :: class
|
|
+T_MODULE+ :: module
|
|
+T_FLOAT+ :: floating point number
|
|
+T_STRING+ :: string
|
|
+T_REGEXP+ :: regular expression
|
|
+T_ARRAY+ :: array
|
|
+T_HASH+ :: associative array
|
|
+T_STRUCT+ :: (Ruby) structure
|
|
+T_BIGNUM+ :: multi precision integer
|
|
+T_FIXNUM+ :: Fixnum(31bit or 63bit integer)
|
|
+T_COMPLEX+ :: complex number
|
|
+T_RATIONAL+ :: rational number
|
|
+T_FILE+ :: IO
|
|
+T_TRUE+ :: +true+
|
|
+T_FALSE+ :: +false+
|
|
+T_DATA+ :: data
|
|
+T_SYMBOL+ :: symbol
|
|
|
|
In addition, there are several other types used internally:
|
|
|
|
+T_ICLASS+ :: included module
|
|
+T_MATCH+ :: MatchData object
|
|
+T_UNDEF+ :: undefined
|
|
+T_NODE+ :: syntax tree node
|
|
+T_ZOMBIE+ :: object awaiting finalization
|
|
|
|
Most of the types are represented by C structures.
|
|
|
|
=== Check type of the VALUE data
|
|
|
|
The macro <tt>TYPE()</tt> defined in ruby.h shows the data type of the VALUE.
|
|
<tt>TYPE()</tt> returns the constant number <tt>T_</tt>_XXXX_ described above.
|
|
To handle data types, your code will look something like this:
|
|
|
|
switch (TYPE(obj)) {
|
|
case T_FIXNUM:
|
|
/* process Fixnum */
|
|
break;
|
|
case T_STRING:
|
|
/* process String */
|
|
break;
|
|
case T_ARRAY:
|
|
/* process Array */
|
|
break;
|
|
default:
|
|
/* raise exception */
|
|
rb_raise(rb_eTypeError, "not valid value");
|
|
break;
|
|
}
|
|
|
|
There is the data type check function
|
|
|
|
void Check_Type(VALUE value, int type)
|
|
|
|
which raises an exception if the VALUE does not have the type
|
|
specified.
|
|
|
|
There are also faster check macros for fixnums and nil.
|
|
|
|
FIXNUM_P(obj)
|
|
NIL_P(obj)
|
|
|
|
=== Convert VALUE into C data
|
|
|
|
The data for type +T_NIL+, +T_FALSE+, +T_TRUE+ are +nil+, +false+,
|
|
+true+ respectively. They are singletons for the data type. The
|
|
equivalent C constants are: +Qnil+, +Qfalse+, +Qtrue+.
|
|
<tt>RTEST()</tt> will return true if a VALUE is neither +Qfalse+ nor
|
|
+Qnil+. If you need to differentiate +Qfalse+ from +Qnil+,
|
|
specifically test against +Qfalse+.
|
|
|
|
The +T_FIXNUM+ data is a 31bit or 63bit length fixed integer. This
|
|
size depends on the size of long: if long is 32bit then +T_FIXNUM+ is
|
|
31bit, if long is 64bit then +T_FIXNUM+ is 63bit. +T_FIXNUM+ can be
|
|
converted to a C integer by using the <tt>FIX2INT()</tt> macro or
|
|
<tt>FIX2LONG()</tt>. Though you have to check that the data is really
|
|
FIXNUM before using them, they are faster. <tt>FIX2LONG()</tt> never
|
|
raises exceptions, but <tt>FIX2INT()</tt> raises RangeError if the
|
|
result is bigger or smaller than the size of int. There are also
|
|
<tt>NUM2INT()</tt> and <tt>NUM2LONG()</tt> which converts any Ruby
|
|
numbers into C integers. These macros include a type check, so an
|
|
exception will be raised if the conversion failed. <tt>NUM2DBL()</tt>
|
|
can be used to retrieve the double float value in the same way.
|
|
|
|
You can use the macros <tt>StringValue()</tt> and
|
|
<tt>StringValuePtr()</tt> to get a <tt>char*</tt> from a VALUE.
|
|
<tt>StringValue(var)</tt> replaces var's value with the result of
|
|
"var.to_str()". <tt>StringValuePtr(var)</tt> does the same
|
|
replacement and returns the char* representation of var. These macros
|
|
will skip the replacement if var is a String. Notice that the macros
|
|
take only the lvalue as their argument, to change the value of var in
|
|
place.
|
|
|
|
You can also use the macro named <tt>StringValueCStr()</tt>. This is
|
|
just like <tt>StringValuePtr()</tt>, but always adds a NUL character
|
|
at the end of the result. If the result contains a NUL character, this
|
|
macro causes the ArgumentError exception. <tt>StringValuePtr()</tt>
|
|
doesn't guarantee the existence of a NUL at the end of the result, and
|
|
the result may contain NUL.
|
|
|
|
Other data types have corresponding C structures, e.g. <tt>struct
|
|
RArray</tt> for +T_ARRAY+ etc. The VALUE of the type which has the
|
|
corresponding structure can be cast to retrieve the pointer to the
|
|
struct. The casting macro will be of the form RXXXX for each data
|
|
type; for instance, <tt>RARRAY(obj)</tt>. See "ruby.h". However, we
|
|
do not recommend to access RXXXX data directly because these data
|
|
structures are complex. Use corresponding rb_xxx() functions to
|
|
access the internal struct. For example, to access an entry of array,
|
|
use <tt>rb_ary_entry(ary, offset)</tt> and <tt>rb_ary_store(ary,
|
|
offset, obj)</tt>.
|
|
|
|
There are some accessing macros for structure members, for example
|
|
<code>RSTRING_LEN(str)</code> to get the size of the Ruby String object. The
|
|
allocated region can be accessed by <code>RSTRING_PTR(str)</code>.
|
|
|
|
Notice: Do not change the value of the structure directly, unless you
|
|
are responsible for the result. This ends up being the cause of
|
|
interesting bugs.
|
|
|
|
=== Convert C data into VALUE
|
|
|
|
To convert C data to Ruby values:
|
|
|
|
+FIXNUM+ ::
|
|
|
|
left shift 1 bit, and turn on its least significant bit (LSB).
|
|
|
|
Other pointer values ::
|
|
|
|
cast to VALUE.
|
|
|
|
You can determine whether a VALUE is a pointer or not by checking its LSB.
|
|
|
|
Notice: Ruby does not allow arbitrary pointer values to be a VALUE. They
|
|
should be pointers to the structures which Ruby knows about. The known
|
|
structures are defined in <ruby.h>.
|
|
|
|
To convert C numbers to Ruby values, use these macros:
|
|
|
|
<tt>INT2FIX()</tt> :: for integers within 31bits.
|
|
<tt>INT2NUM()</tt> :: for arbitrary sized integers.
|
|
|
|
<tt>INT2NUM()</tt> converts an integer into a Bignum if it is out
|
|
of the +FIXNUM+ range, but is a bit slower.
|
|
|
|
=== Manipulating Ruby object
|
|
|
|
As I already mentioned, it is not recommended to modify an object's
|
|
internal structure. To manipulate objects, use the functions supplied
|
|
by the Ruby interpreter. Some (not all) of the useful functions are
|
|
listed below:
|
|
|
|
==== String functions
|
|
|
|
<tt>rb_str_new(const char *ptr, rb_len_t len)</tt> ::
|
|
|
|
Creates a new Ruby string.
|
|
|
|
<tt>rb_str_new2(const char *ptr)</tt> ::
|
|
<tt>rb_str_new_cstr(const char *ptr)</tt> ::
|
|
|
|
Creates a new Ruby string from a C string. This is equivalent to
|
|
<tt>rb_str_new(ptr, strlen(ptr))</tt>.
|
|
|
|
<tt>rb_str_new_literal(const char *ptr)</tt> ::
|
|
|
|
Creates a new Ruby string from a C string literal.
|
|
|
|
<tt>rb_sprintf(const char *format, ...)</tt> ::
|
|
<tt>rb_vsprintf(const char *format, va_list ap)</tt> ::
|
|
|
|
Creates a new Ruby string with printf(3) format.
|
|
|
|
Note: In the format string, <tt>"%"PRIsVALUE</tt> can be used for Object#to_s
|
|
(or Object#inspect if <tt>+</tt> flag is set) output (and related argument
|
|
must be a VALUE). Since it conflicts with <tt>"%i"</tt>, for integers in
|
|
format strings, use <tt>"%d"</tt>.
|
|
|
|
<tt>rb_str_append(VALUE str1, VALUE str2)</tt> ::
|
|
|
|
Appends Ruby string str2 to Ruby string str1.
|
|
|
|
<tt>rb_str_cat(VALUE str, const char *ptr, rb_len_t len)</tt> ::
|
|
|
|
Appends len bytes of data from ptr to the Ruby string.
|
|
|
|
<tt>rb_str_cat2(VALUE str, const char* ptr)</tt> ::
|
|
<tt>rb_str_cat_cstr(VALUE str, const char* ptr)</tt> ::
|
|
|
|
Appends C string ptr to Ruby string str. This function is
|
|
equivalent <tt>to rb_str_cat(str, ptr, strlen(ptr))</tt>.
|
|
|
|
<tt>rb_str_catf(VALUE str, const char* format, ...)</tt> ::
|
|
<tt>rb_str_vcatf(VALUE str, const char* format, va_list ap)</tt> ::
|
|
|
|
Appends C string format and successive arguments to Ruby string
|
|
str according to a printf-like format. These functions are
|
|
equivalent to <tt>rb_str_append(str, rb_sprintf(format, ...))</tt> and
|
|
<tt>rb_str_append(str, rb_vsprintf(format, ap))</tt>, respectively.
|
|
|
|
<tt>rb_enc_str_new(const char *ptr, rb_len_t len, rb_encoding *enc)</tt> ::
|
|
<tt>rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)</tt> ::
|
|
|
|
Creates a new Ruby string with the specified encoding.
|
|
|
|
<tt>rb_enc_str_new_literal(const char *ptr, rb_encoding *enc)</tt> ::
|
|
|
|
Creates a new Ruby string from a C string literal with the specified
|
|
encoding.
|
|
|
|
<tt>rb_usascii_str_new(const char *ptr, rb_len_t len)</tt> ::
|
|
<tt>rb_usascii_str_new_cstr(const char *ptr)</tt> ::
|
|
|
|
Creates a new Ruby string with encoding US-ASCII.
|
|
|
|
<tt>rb_usascii_str_new_literal(const char *ptr)</tt> ::
|
|
|
|
Creates a new Ruby string from a C string literal with encoding
|
|
US-ASCII.
|
|
|
|
<tt>rb_utf8_str_new(const char *ptr, rb_len_t len)</tt> ::
|
|
<tt>rb_utf8_str_new_cstr(const char *ptr)</tt> ::
|
|
|
|
Creates a new Ruby string with encoding UTF-8.
|
|
|
|
<tt>rb_utf8_str_new_literal(const char *ptr)</tt> ::
|
|
|
|
Creates a new Ruby string from a C string literal with encoding
|
|
UTF-8.
|
|
|
|
<tt>rb_str_resize(VALUE str, rb_len_t len)</tt> ::
|
|
|
|
Resizes a Ruby string to len bytes. If str is not modifiable, this
|
|
function raises an exception. The length of str must be set in
|
|
advance. If len is less than the old length the content beyond
|
|
len bytes is discarded, else if len is greater than the old length
|
|
the content beyond the old length bytes will not be preserved but
|
|
will be garbage. Note that <tt>RSTRING_PTR(str)</tt> may change by calling
|
|
this function.
|
|
|
|
<tt>rb_str_set_len(VALUE str, rb_len_t len)</tt> ::
|
|
|
|
Sets the length of a Ruby string. If str is not modifiable, this
|
|
function raises an exception. This function preserves the content
|
|
up to len bytes, regardless <tt>RSTRING_LEN(str)</tt>. len must not exceed
|
|
the capacity of str.
|
|
|
|
<tt>rb_str_modify(VALUE str)</tt> ::
|
|
|
|
Prepares a Ruby string to modify. If str is not modifiable, this
|
|
function raises an exception, or if the buffer of str is shared,
|
|
this function allocates new buffer to make it unshared. Always
|
|
you MUST call this function before modifying the contents using
|
|
+RSTRING_PTR+ and/or +rb_str_set_len+.
|
|
|
|
==== Array functions
|
|
|
|
<tt>rb_ary_new()</tt> ::
|
|
|
|
Creates an array with no elements.
|
|
|
|
<tt>rb_ary_new2(rb_len_t len)</tt> ::
|
|
<tt>rb_ary_new_capa(rb_len_t len)</tt> ::
|
|
|
|
Creates an array with no elements, allocating internal buffer
|
|
for len elements.
|
|
|
|
<tt>rb_ary_new3(rb_len_t n, ...)</tt> ::
|
|
<tt>rb_ary_new_from_args(rb_len_t n, ...)</tt> ::
|
|
|
|
Creates an n-element array from the arguments.
|
|
|
|
<tt>rb_ary_new4(rb_len_t n, VALUE *elts)</tt> ::
|
|
<tt>rb_ary_new_from_values(rb_len_t n, VALUE *elts)</tt> ::
|
|
|
|
Creates an n-element array from a C array.
|
|
|
|
<tt>rb_ary_to_ary(VALUE obj)</tt> ::
|
|
|
|
Converts the object into an array.
|
|
Equivalent to Object#to_ary.
|
|
|
|
There are many functions to operate an array. They may dump core if other
|
|
types are given.
|
|
|
|
<tt>rb_ary_aref(int argc, const VALUE *argv, VALUE ary)</tt> ::
|
|
|
|
Equivalent to Array#[].
|
|
|
|
<tt>rb_ary_entry(VALUE ary, rb_len_t offset)</tt> ::
|
|
|
|
<tt>ary[offset]</tt>
|
|
|
|
<tt>rb_ary_store(VALUE ary, rb_len_t offset, VALUE obj)</tt> ::
|
|
|
|
<tt>ary[offset] = obj</tt>
|
|
|
|
<tt>rb_ary_subseq(VALUE ary, rb_len_t beg, rb_len_t len)</tt> ::
|
|
|
|
<tt>ary[beg, len]</tt>
|
|
|
|
<tt>rb_ary_push(VALUE ary, VALUE val)</tt> ::
|
|
<tt>rb_ary_pop(VALUE ary)</tt> ::
|
|
<tt>rb_ary_shift(VALUE ary)</tt> ::
|
|
<tt>rb_ary_unshift(VALUE ary, VALUE val)</tt> ::
|
|
|
|
<tt>ary.push(val)</tt>, <tt>ary.pop</tt>, <tt>ary.shift</tt>, <tt>ary.unshift(val)</tt>
|
|
|
|
<tt>rb_ary_cat(VALUE ary, const VALUE *ptr, rb_len_t len)</tt> ::
|
|
|
|
Appends _len_ elements of objects from _ptr_ to the array.
|
|
|
|
== Extending Ruby with C
|
|
|
|
=== Adding new features to Ruby
|
|
|
|
You can add new features (classes, methods, etc.) to the Ruby
|
|
interpreter. Ruby provides APIs for defining the following things:
|
|
|
|
- Classes, Modules
|
|
- Methods, singleton methods
|
|
- Constants
|
|
|
|
==== Class and Module Definition
|
|
|
|
To define a class or module, use the functions below:
|
|
|
|
VALUE rb_define_class(const char *name, VALUE super)
|
|
VALUE rb_define_module(const char *name)
|
|
|
|
These functions return the newly created class or module. You may
|
|
want to save this reference into a variable to use later.
|
|
|
|
To define nested classes or modules, use the functions below:
|
|
|
|
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
|
|
VALUE rb_define_module_under(VALUE outer, const char *name)
|
|
|
|
==== Method and singleton method definition
|
|
|
|
To define methods or singleton methods, use these functions:
|
|
|
|
void rb_define_method(VALUE klass, const char *name,
|
|
VALUE (*func)(ANYARGS), int argc)
|
|
|
|
void rb_define_singleton_method(VALUE object, const char *name,
|
|
VALUE (*func)(ANYARGS), int argc)
|
|
|
|
The _argc_ represents the number of the arguments to the C function,
|
|
which must be less than 17. But I doubt you'll need that many.
|
|
|
|
If _argc_ is negative, it specifies the calling sequence, not number of
|
|
the arguments.
|
|
|
|
If _argc_ is -1, the function will be called as:
|
|
|
|
VALUE func(int argc, VALUE *argv, VALUE obj)
|
|
|
|
where _argc_ is the actual number of arguments, _argv_ is the C array of
|
|
the arguments, and _obj_ is the receiver.
|
|
|
|
If _argc_ is -2, the arguments are passed in a Ruby array. The function
|
|
will be called like:
|
|
|
|
VALUE func(VALUE obj, VALUE args)
|
|
|
|
where _obj_ is the receiver, and _args_ is the Ruby array containing
|
|
actual arguments.
|
|
|
|
There are some more functions to define methods. One takes an ID
|
|
as the name of method to be defined. See also ID or Symbol below.
|
|
|
|
void rb_define_method_id(VALUE klass, ID name,
|
|
VALUE (*func)(ANYARGS), int argc)
|
|
|
|
There are two functions to define private/protected methods:
|
|
|
|
void rb_define_private_method(VALUE klass, const char *name,
|
|
VALUE (*func)(ANYARGS), int argc)
|
|
void rb_define_protected_method(VALUE klass, const char *name,
|
|
VALUE (*func)(ANYARGS), int argc)
|
|
|
|
At last, +rb_define_module_function+ defines a module function,
|
|
which are private AND singleton methods of the module.
|
|
For example, +sqrt+ is a module function defined in the Math module.
|
|
It can be called in the following way:
|
|
|
|
Math.sqrt(4)
|
|
|
|
or
|
|
|
|
include Math
|
|
sqrt(4)
|
|
|
|
To define module functions, use:
|
|
|
|
void rb_define_module_function(VALUE module, const char *name,
|
|
VALUE (*func)(ANYARGS), int argc)
|
|
|
|
In addition, function-like methods, which are private methods defined
|
|
in the Kernel module, can be defined using:
|
|
|
|
void rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
|
|
|
|
To define an alias for the method,
|
|
|
|
void rb_define_alias(VALUE module, const char* new, const char* old);
|
|
|
|
To define a reader/writer for an attribute,
|
|
|
|
void rb_define_attr(VALUE klass, const char *name, int read, int write)
|
|
|
|
To define and undefine the +allocate+ class method,
|
|
|
|
void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE klass));
|
|
void rb_undef_alloc_func(VALUE klass);
|
|
|
|
_func_ has to take the _klass_ as the argument and return a newly
|
|
allocated instance. This instance should be as empty as possible,
|
|
without any expensive (including external) resources.
|
|
|
|
If you are overriding an existing method of any ancestor of your class,
|
|
you may rely on:
|
|
|
|
VALUE rb_call_super(int argc, const VALUE *argv)
|
|
|
|
To specify whether keyword arguments are passed when calling super:
|
|
|
|
VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
|
|
|
|
_kw_splat_ can have these possible values (used by all methods that accept
|
|
_kw_splat_ argument):
|
|
|
|
+RB_NO_KEYWORDS+ :: Do not pass keywords
|
|
+RB_PASS_KEYWORDS+ :: Pass keywords, final argument should be a hash of keywords
|
|
+RB_PASS_CALLED_KEYWORDS+ :: Pass keywords if current method was called with
|
|
keywords, useful for argument delegation
|
|
|
|
To achieve the receiver of the current scope (if no other way is
|
|
available), you can use:
|
|
|
|
VALUE rb_current_receiver(void)
|
|
|
|
==== Constant definition
|
|
|
|
We have 2 functions to define constants:
|
|
|
|
void rb_define_const(VALUE klass, const char *name, VALUE val)
|
|
void rb_define_global_const(const char *name, VALUE val)
|
|
|
|
The former is to define a constant under specified class/module. The
|
|
latter is to define a global constant.
|
|
|
|
=== Use Ruby features from C
|
|
|
|
There are several ways to invoke Ruby's features from C code.
|
|
|
|
==== Evaluate Ruby programs in a string
|
|
|
|
The easiest way to use Ruby's functionality from a C program is to
|
|
evaluate the string as Ruby program. This function will do the job:
|
|
|
|
VALUE rb_eval_string(const char *str)
|
|
|
|
Evaluation is done under the current context, thus current local variables
|
|
of the innermost method (which is defined by Ruby) can be accessed.
|
|
|
|
Note that the evaluation can raise an exception. There is a safer
|
|
function:
|
|
|
|
VALUE rb_eval_string_protect(const char *str, int *state)
|
|
|
|
It returns +nil+ when an error occurred. Moreover, <code>*state</code> is
|
|
zero if _str_ was successfully evaluated, or nonzero otherwise.
|
|
|
|
==== ID or Symbol
|
|
|
|
You can invoke methods directly, without parsing the string. First I
|
|
need to explain about ID. ID is the integer number to represent
|
|
Ruby's identifiers such as variable names. The Ruby data type
|
|
corresponding to ID is Symbol. It can be accessed from Ruby in the
|
|
form:
|
|
|
|
:Identifier
|
|
|
|
or
|
|
|
|
:"any kind of string"
|
|
|
|
You can get the ID value from a string within C code by using
|
|
|
|
rb_intern(const char *name)
|
|
rb_intern_str(VALUE name)
|
|
|
|
You can retrieve ID from Ruby object (Symbol or String) given as an
|
|
argument by using
|
|
|
|
rb_to_id(VALUE symbol)
|
|
rb_check_id(volatile VALUE *name)
|
|
rb_check_id_cstr(const char *name, rb_len_t len, rb_encoding *enc)
|
|
|
|
These functions try to convert the argument to a String if it was not a
|
|
Symbol nor a String. The second function stores the converted result into
|
|
<code>*name</code>, and returns 0 if the string is not a known symbol.
|
|
After this function returned a non-zero value, <code>*name</code> is
|
|
always a Symbol or a String, otherwise it is a String if the result is
|
|
0. The third function takes C string (pointer to +char+ array) and its
|
|
length, not Ruby VALUE.
|
|
|
|
You can retrieve Symbol from Ruby object (Symbol or String) given as
|
|
an argument by using
|
|
|
|
rb_to_symbol(VALUE name)
|
|
rb_check_symbol(volatile VALUE *namep)
|
|
rb_check_symbol_cstr(const char *ptr, rb_len_t len, rb_encoding *enc)
|
|
|
|
These functions are similar to above functions except that these
|
|
return a Symbol instead of an ID.
|
|
|
|
You can convert C ID to Ruby Symbol by using
|
|
|
|
VALUE ID2SYM(ID id)
|
|
|
|
and to convert Ruby Symbol object to ID, use
|
|
|
|
ID SYM2ID(VALUE symbol)
|
|
|
|
==== Invoke Ruby method from C
|
|
|
|
To invoke methods directly, you can use the function below
|
|
|
|
VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
|
|
|
|
This function invokes a method on the _recv_, with the method name
|
|
specified by the symbol _mid_.
|
|
|
|
==== Accessing the variables and constants
|
|
|
|
You can access class variables and instance variables using access
|
|
functions. Also, global variables can be shared between both
|
|
environments. There's no way to access Ruby's local variables.
|
|
|
|
The functions to access/modify instance variables are below:
|
|
|
|
VALUE rb_ivar_get(VALUE obj, ID id)
|
|
VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
|
|
|
|
_id_ must be the symbol, which can be retrieved by <tt>rb_intern()</tt>.
|
|
|
|
To access the constants of the class/module:
|
|
|
|
VALUE rb_const_get(VALUE obj, ID id)
|
|
|
|
See also Constant Definition above.
|
|
|
|
== Information sharing between Ruby and C
|
|
|
|
=== Ruby constants that can be accessed from C
|
|
|
|
As stated in section 1.3,
|
|
the following Ruby constants can be referred from C.
|
|
|
|
<tt>Qtrue</tt> ::
|
|
<tt>Qfalse</tt> ::
|
|
|
|
Boolean values. +Qfalse+ is +false+ in C also (i.e. 0).
|
|
|
|
<tt>Qnil</tt> ::
|
|
|
|
Ruby +nil+ in C scope.
|
|
|
|
=== Global variables shared between C and Ruby
|
|
|
|
Information can be shared between the two environments using shared global
|
|
variables. To define them, you can use functions listed below:
|
|
|
|
void rb_define_variable(const char *name, VALUE *var)
|
|
|
|
This function defines the variable which is shared by both environments.
|
|
The value of the global variable pointed to by _var_ can be accessed
|
|
through Ruby's global variable named _name_.
|
|
|
|
You can define read-only (from Ruby, of course) variables using the
|
|
function below.
|
|
|
|
void rb_define_readonly_variable(const char *name, VALUE *var)
|
|
|
|
You can define hooked variables. The accessor functions (_getter_ and
|
|
_setter_) are called on access to the hooked variables.
|
|
|
|
void rb_define_hooked_variable(const char *name, VALUE *var,
|
|
VALUE (*getter)(), void (*setter)())
|
|
|
|
If you need to supply either setter or getter, just supply 0 for the
|
|
hook you don't need. If both hooks are 0, <tt>rb_define_hooked_variable()</tt>
|
|
works just like <tt>rb_define_variable()</tt>.
|
|
|
|
The prototypes of the _getter_ and _setter_ functions are as follows:
|
|
|
|
VALUE (*getter)(ID id, VALUE *var);
|
|
void (*setter)(VALUE val, ID id, VALUE *var);
|
|
|
|
Also you can define a Ruby global variable without a corresponding C
|
|
variable. The value of the variable will be set/get only by hooks.
|
|
|
|
void rb_define_virtual_variable(const char *name,
|
|
VALUE (*getter)(), void (*setter)())
|
|
|
|
The prototypes of the _getter_ and _setter_ functions are as follows:
|
|
|
|
VALUE (*getter)(ID id);
|
|
void (*setter)(VALUE val, ID id);
|
|
|
|
=== Encapsulate C data into a Ruby object
|
|
|
|
Sometimes you need to expose your struct in the C world as a Ruby
|
|
object.
|
|
In a situation like this, making use of the TypedData_XXX macro
|
|
family, the pointer to the struct and the Ruby object can be mutually
|
|
converted.
|
|
|
|
--
|
|
The old (non-Typed) Data_XXX macro family has been deprecated.
|
|
In the future version of Ruby, it is possible old macros will not
|
|
work.
|
|
++
|
|
|
|
==== C struct to Ruby object
|
|
|
|
You can convert _sval_, a pointer to your struct, into a Ruby object with the
|
|
next macro.
|
|
|
|
TypedData_Wrap_Struct(klass, data_type, sval)
|
|
|
|
<tt>TypedData_Wrap_Struct()</tt> returns a created Ruby object as a
|
|
VALUE.
|
|
|
|
This macro cannot be used with data types that have the +RUBY_TYPED_EMBEDDABLE+
|
|
flag; use +TypedData_Make_Struct+ or +rb_data_typed_object_zalloc+ for such
|
|
types.
|
|
|
|
The _klass_ argument is the class for the object. The _klass_ should derive
|
|
from _rb_cObject_, and the allocator must be set by calling
|
|
+rb_define_alloc_func+ or +rb_undef_alloc_func+.
|
|
|
|
_data_type_ is a pointer to a const +rb_data_type_t+ which describes how Ruby
|
|
should manage the struct.
|
|
|
|
+rb_data_type_t+ is roughly defined like this. Fields reserved for future use
|
|
are omitted.
|
|
|
|
typedef struct rb_data_type_struct rb_data_type_t;
|
|
|
|
struct rb_data_type_struct {
|
|
const char *wrap_struct_name;
|
|
struct {
|
|
void (*dmark)(void*);
|
|
void (*dfree)(void*);
|
|
size_t (*dsize)(const void *);
|
|
void (*dcompact)(void*);
|
|
/* reserved fields */
|
|
} function;
|
|
const rb_data_type_t *parent;
|
|
void *data;
|
|
VALUE flags;
|
|
};
|
|
|
|
+wrap_struct_name+ is an identifier of this instance of the struct. It is
|
|
basically used for collecting and emitting statistics. So the identifier should
|
|
be unique in the process, but doesn't need to be valid as a C or Ruby
|
|
identifier.
|
|
|
|
These +dmark+ / +dfree+ functions are invoked during GC execution. No object
|
|
allocations are allowed during it, so do not allocate ruby objects inside them.
|
|
|
|
+dmark+ is a function to mark Ruby objects referred from your struct. It must
|
|
mark all references from your struct with +rb_gc_mark+ or its family if your
|
|
struct keeps such references.
|
|
|
|
--
|
|
Note that it is recommended to avoid such a reference.
|
|
++
|
|
|
|
+dfree+ is a function to free the pointer allocation. If this is
|
|
+RUBY_DEFAULT_FREE+, the pointer will be just freed.
|
|
|
|
+dsize+ calculates memory consumption in bytes by the struct. Its parameter is
|
|
a pointer to your struct. You can pass 0 as dsize if it is hard to implement
|
|
such a function. But it is still recommended to avoid 0.
|
|
|
|
+dcompact+ is invoked when memory compaction took place. Referred Ruby objects
|
|
that were marked by <tt>rb_gc_mark_movable()</tt> can here be updated per
|
|
<tt>rb_gc_location()</tt>.
|
|
|
|
+parent+ can point to another C type definition that the Ruby object is
|
|
inherited from. Then <tt>TypedData_Get_Struct()</tt> does also accept
|
|
derived objects.
|
|
|
|
You can fill +data+ with an arbitrary value for your use. Ruby does nothing
|
|
with the member.
|
|
|
|
+flags+ is a bitwise-OR of the following flag values. Since they require deep
|
|
understanding of garbage collector in Ruby, you can just set 0 to +flags+ if you
|
|
are not sure.
|
|
|
|
+RUBY_TYPED_FREE_IMMEDIATELY+ ::
|
|
|
|
This flag allows the garbage collector to immediately invoke <tt>dfree()</tt>
|
|
during GC when it needs to free your struct.
|
|
You can specify this flag if the <tt>dfree</tt> never unlocks Ruby's
|
|
internal lock (GVL).
|
|
|
|
If this flag is not set, Ruby defers invocation of <tt>dfree()</tt>
|
|
and invokes <tt>dfree()</tt> at the same time as finalizers.
|
|
|
|
+RUBY_TYPED_THREAD_SAFE_FREE+ ::
|
|
|
|
This flag declares that the <tt>dfree()</tt> function is thread-safe.
|
|
|
|
With this flag set the garbage collector MAY invoke <tt>dfree()</tt>
|
|
* On any thread, whether a Ruby Thread or a native thread
|
|
* In parallel with calls to the same or other <tt>dfree</tt> functions
|
|
* Concurrently with other Ruby code
|
|
|
|
This should NOT be set on <tt>dfree()</tt> functions which access shared state
|
|
in a thread-unsafe way. A <tt>dfree()</tt> function which uses only
|
|
<tt>xfree()</tt> on the struct and memory it exclusively owns is thread-safe.
|
|
|
|
This flag implies +RUBY_TYPED_FREE_IMMEDIATELY+, since a thread-safe
|
|
<tt>dfree()</tt> is also safe to invoke immediately.
|
|
|
|
+RUBY_TYPED_WB_PROTECTED+ ::
|
|
|
|
It shows that implementation of the object supports write barriers.
|
|
If this flag is set, Ruby is better able to do garbage collection
|
|
of the object.
|
|
|
|
When it is set, however, you are responsible for putting write
|
|
barriers in all implementations of methods of that object as
|
|
appropriate. Otherwise Ruby might crash while running.
|
|
|
|
More about write barriers can be found in {Generational
|
|
GC}[rdoc-ref:@Appendix+D.+Generational+GC].
|
|
|
|
+RUBY_TYPED_FROZEN_SHAREABLE+ ::
|
|
|
|
This flag indicates that the object is shareable object if the object
|
|
is frozen. See {Ractor support}[rdoc-ref:@Appendix+F.+Ractor+support]
|
|
more details.
|
|
|
|
If this flag is not set, the object can not become a shareable
|
|
object by <tt>Ractor.make_shareable()</tt> method.
|
|
|
|
+RUBY_TYPED_EMBEDDABLE+ ::
|
|
|
|
This flag indicates that Ruby may store the C struct inside the object
|
|
slot, rather than allocate it separately with +malloc+.
|
|
However, it is not a guarantee. Ruby may decide not to embed the object.
|
|
For instance if it's too large to fit into one of the available slot sizes.
|
|
|
|
Embedding the C struct inside the object slot reduces pointer chasing,
|
|
+malloc+ overhead, and improves sweep performance. In some cases, it can also
|
|
reduce the memory footprint of the object.
|
|
|
|
To be embeddable, types must abide by some restrictions:
|
|
|
|
* Pointers to the C struct, or into the C struct, MUST NOT be stored,
|
|
as they become invalid when GC compaction occurs.
|
|
It is however valid to pass and use such pointers for as long as the Ruby
|
|
object remains on the stack.
|
|
|
|
In a sense, this is similar to the restrictions of a stack allocated struct.
|
|
|
|
The +RB_GC_GUARD+ macro must be used to ensure the object is not moved by
|
|
compaction and not freed, unless the object is passed directly as an
|
|
argument from Ruby to C, i.e. as a parameter of a function used with
|
|
+rb_define_method+ and similar.
|
|
|
|
* The +DATA_PTR+, +RTYPEDDATA_DATA+ and +TypedData_Wrap_Struct+ macro can't be
|
|
used.
|
|
Only +RTYPEDDATA_GET_DATA+ or +TypedData_Get_Struct+ macros can be used with
|
|
embeddable objects. Accessing <tt>RTYPEDDATA(obj)->data</tt> is invalid too.
|
|
|
|
* The +dfree+ function MUST NOT free the C struct itself.
|
|
Setting +dfree+ to +RUBY_DEFAULT_FREE+ is fine.
|
|
To support older Ruby versions without this feature, you can
|
|
conditionally free the C struct if +RUBY_TYPED_EMBEDDABLE+ isn't defined.
|
|
|
|
* The type must have the +RUBY_TYPED_FREE_IMMEDIATELY+ flag set.
|
|
|
|
If the embedded C struct is of variable size, +rb_data_typed_object_zalloc+
|
|
can be used instead of +TypedData_Make_Struct+.
|
|
|
|
See {Embedded TypedData}[rdoc-ref:@Appendix+G.+Embedded+TypedData] for a
|
|
commented example of how to use +RUBY_TYPED_EMBEDDABLE+.
|
|
|
|
Fields other than those listed above are reserved for future use, and
|
|
initializers are typically omitted. In the rare case that you need to
|
|
dynamically allocate a +rb_data_type_t+, these fields must be filled with
|
|
zeros.
|
|
|
|
Note that this macro can raise an exception. If _sval_ already holds a
|
|
resource that must be released, such as allocated memory or a handle from an
|
|
external library, protect the call with +rb_protect+ and release the resource
|
|
when an exception is raised. Alternatively, create the object first with a
|
|
+NULL+ data pointer, then allocate the resource and store it in the object.
|
|
|
|
You can allocate and wrap the structure in one step, in more
|
|
preferable manner.
|
|
|
|
obj = TypedData_Make_Struct(klass, type, data_type, sval)
|
|
|
|
This macro returns an allocated +T_DATA+ object, wrapping the pointer to the
|
|
structure, which is also allocated. This macro works like:
|
|
|
|
obj = TypedData_Wrap_Struct(klass, data_type, NULL);
|
|
RTYPEDDATA_DATA(obj) = sval = ZALLOC(type);
|
|
|
|
However, you should use this macro instead of "allocation then wrap" like the
|
|
above code if it is simply allocated, because the "wrap" can raise a
|
|
+NoMemoryError+ and _sval_ will be memory leaked in that case.
|
|
|
|
Arguments _klass_ and _data_type_ work like their counterparts in
|
|
<tt>TypedData_Wrap_Struct()</tt>. A pointer to the allocated structure will be
|
|
assigned to _sval_, which should be a pointer of the type specified.
|
|
|
|
Same for other than simple memory allocation:
|
|
|
|
obj = TypedData_Wrap_Struct(klass, data_type, NULL);
|
|
sval = allocate_some_resource();
|
|
if (success(sval)) RTYPEDDATA_DATA(obj) = sval;
|
|
|
|
You may have to cast _sval_ to <tt>void*</tt>, if it is not a pointer type.
|
|
|
|
==== Declaratively marking/compacting struct references
|
|
|
|
In the case where your struct refers to Ruby objects that are simple values,
|
|
not wrapped in conditional logic or complex data structures an alternative
|
|
approach to marking and reference updating is provided, by declaring offset
|
|
references to the VALUEs (or edge) in your struct.
|
|
|
|
Doing this allows the Ruby GC to support marking these references and GC
|
|
compaction without the need to define the +dmark+ and +dcompact+ callbacks.
|
|
|
|
You must define a static list of VALUE pointers to the offsets within your
|
|
struct where the references are located, and set the +data+ member to point
|
|
to this reference list. The reference list must end with +RUBY_END_REFS+.
|
|
|
|
Some macros have been provided to make edge referencing easier:
|
|
|
|
<tt>RUBY_TYPED_DECL_MARKING</tt> ::
|
|
A flag that can be set on the +ruby_data_type_t+ to indicate that
|
|
references are being declared as edges.
|
|
<tt>RUBY_REFERENCES(ref_list_name)</tt> ::
|
|
Define _ref_list_name_ as a list of references
|
|
<tt>RUBY_REF_END</tt> :: The end mark of the references list.
|
|
<tt>RUBY_REF_EDGE(struct, member)</tt> ::
|
|
Declare _member_ as a VALUE edge from _struct_. Use this inside
|
|
the block of +RUBY_REFERENCES+.
|
|
+RUBY_REFS_LIST_PTR+ ::
|
|
Coerce the reference list into a format that can be accepted by the
|
|
existing +dmark+ interface.
|
|
|
|
The example below is from Dir (defined in +dir.c+)
|
|
|
|
// The struct being wrapped. Notice this contains 3 members of which the second
|
|
// is a VALUE reference to another ruby object.
|
|
struct dir_data {
|
|
DIR *dir;
|
|
const VALUE path;
|
|
rb_encoding *enc;
|
|
}
|
|
|
|
// Define a reference list `dir_refs` containing a single entry to `path`.
|
|
// Needs terminating with RUBY_REF_END
|
|
RUBY_REFERENCES(dir_refs) = {
|
|
RUBY_REF_EDGE(dir_data, path),
|
|
RUBY_REF_END
|
|
};
|
|
|
|
// Override the "dmark" field with the defined reference list now that we
|
|
// no longer need a marking callback and add RUBY_TYPED_DECL_MARKING to the
|
|
// flags field
|
|
static const rb_data_type_t dir_data_type = {
|
|
"dir",
|
|
{RUBY_REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,},
|
|
0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING
|
|
};
|
|
|
|
Declaring simple references declaratively in this manner allows the GC to both
|
|
mark, and move the underlying object, and automatically update the reference to
|
|
it during compaction.
|
|
|
|
==== Ruby object to C struct
|
|
|
|
To retrieve the C pointer from the +T_DATA+ object, use the macro
|
|
<tt>TypedData_Get_Struct()</tt>.
|
|
|
|
TypedData_Get_Struct(obj, type, &data_type, sval)
|
|
|
|
A pointer to the structure will be assigned to the variable _sval_.
|
|
|
|
See the example below for details.
|
|
|
|
== Example - Creating the dbm Extension
|
|
|
|
OK, here's the example of making an extension library. This is the
|
|
extension to access DBMs. The full source is included in the ext/
|
|
directory in the Ruby's source tree.
|
|
|
|
=== Make the directory
|
|
|
|
% mkdir ext/dbm
|
|
|
|
Make a directory for the extension library under ext directory if you
|
|
want to link it to statically Ruby. You can use an arbitrary name.
|
|
|
|
=== Design the Library
|
|
|
|
You need to design the library features, before making it.
|
|
|
|
=== Write the C Code
|
|
|
|
You need to write C code for your extension library. If your library
|
|
has only one source file, choosing ``LIBRARY.c'' as a file name is
|
|
preferred.
|
|
Note that some functions in mkmf library described below generate
|
|
a file ``conftest.c'' for checking with compilation. You shouldn't
|
|
choose ``conftest.c'' as a name of a source file.
|
|
|
|
Ruby will execute the initializing function named +Init_LIBRARY+ in
|
|
the library. For example, <code>Init_dbm()</code> will be executed when
|
|
loading the library.
|
|
|
|
Here's the example of an initializing function.
|
|
|
|
#include <ruby.h>
|
|
void
|
|
Init_dbm(void)
|
|
{
|
|
/* define DBM class */
|
|
VALUE cDBM = rb_define_class("DBM", rb_cObject);
|
|
/* Redefine DBM.allocate
|
|
rb_define_alloc_func(cDBM, fdbm_alloc);
|
|
/* DBM includes Enumerable module */
|
|
rb_include_module(cDBM, rb_mEnumerable);
|
|
|
|
/* DBM has class method open(): arguments are received as C array */
|
|
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
|
|
|
|
/* DBM instance method close(): no args */
|
|
rb_define_method(cDBM, "close", fdbm_close, 0);
|
|
/* DBM instance method []: 1 argument */
|
|
rb_define_method(cDBM, "[]", fdbm_aref, 1);
|
|
|
|
/* ... */
|
|
|
|
/* ID for a instance variable to store DBM data */
|
|
id_dbm = rb_intern("dbm");
|
|
}
|
|
|
|
The dbm extension wraps the dbm struct in the C environment using
|
|
+TypedData_Make_Struct+.
|
|
|
|
struct dbmdata {
|
|
int di_size;
|
|
DBM *di_dbm;
|
|
};
|
|
|
|
static const rb_data_type_t dbm_type = {
|
|
"dbm",
|
|
{0, free_dbm, memsize_dbm,},
|
|
0, 0,
|
|
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
};
|
|
|
|
static VALUE
|
|
fdbm_alloc(VALUE klass)
|
|
{
|
|
struct dbmdata *dbmp;
|
|
/* Allocate T_DATA object and C struct and fill struct with zero bytes */
|
|
return TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp);
|
|
}
|
|
|
|
This code wraps the +dbmdata+ structure into a Ruby object. We avoid
|
|
wrapping <tt>DBM*</tt> directly, because we want to cache size information.
|
|
Since Class.allocate allocates an ordinary +T_OBJECT+ type (instead
|
|
of +T_DATA+), it's important to either use <tt>rb_define_alloc_func()</tt> to
|
|
overwrite it or <tt>rb_undef_alloc_func()</tt> to delete it.
|
|
|
|
To retrieve the +dbmdata+ structure from a Ruby object, we define the
|
|
following macro:
|
|
|
|
#define GetDBM(obj, dbmp) do {\
|
|
TypedData_Get_Struct((obj), struct dbmdata, &dbm_type, (dbmp));\
|
|
if ((dbmp) == 0) closed_dbm();\
|
|
if ((dbmp)->di_dbm == 0) closed_dbm();\
|
|
} while (0)
|
|
|
|
This sort of complicated macro does the retrieving and close checking
|
|
for the DBM.
|
|
|
|
There are three kinds of way to receive method arguments. First,
|
|
methods with a fixed number of arguments receive arguments like this:
|
|
|
|
static VALUE
|
|
fdbm_aref(VALUE obj, VALUE keystr)
|
|
{
|
|
struct dbmdata *dbmp;
|
|
GetDBM(obj, dbmp);
|
|
/* Use dbmp to access the key */
|
|
dbm_fetch(dbmp->di_dbm, StringValueCStr(keystr));
|
|
/* ... */
|
|
}
|
|
|
|
The first argument of the C function is the +self+, the rest are the
|
|
arguments to the method.
|
|
|
|
Second, methods with an arbitrary number of arguments receive
|
|
arguments like this:
|
|
|
|
static VALUE
|
|
fdbm_s_open(int argc, VALUE *argv, VALUE klass)
|
|
{
|
|
/* ... */
|
|
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
|
|
mode = 0666; /* default value */
|
|
}
|
|
/* ... */
|
|
}
|
|
|
|
The first argument is the number of method arguments, the second
|
|
argument is the C array of the method arguments, and the third
|
|
argument is the receiver of the method.
|
|
|
|
You can use the function <tt>rb_scan_args()</tt> to check and retrieve
|
|
the arguments. The third argument is a string that specifies how to
|
|
capture method arguments and assign them to the following VALUE
|
|
references.
|
|
|
|
You can just check the argument number with <tt>rb_check_arity()</tt>,
|
|
this is handy in the case you want to treat the arguments as a list.
|
|
|
|
The following is an example of a method that takes arguments by Ruby's
|
|
array:
|
|
|
|
static VALUE
|
|
thread_initialize(VALUE thread, VALUE args)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
The first argument is the receiver, the second one is the Ruby array
|
|
which contains the arguments to the method.
|
|
|
|
<b>Notice</b>: GC should know about global variables which refer to Ruby's objects,
|
|
but are not exported to the Ruby world. You need to protect them by
|
|
|
|
void rb_global_variable(VALUE *var)
|
|
|
|
or the objects themselves by
|
|
|
|
void rb_gc_register_mark_object(VALUE object)
|
|
|
|
Registration is scoped to the calling Ractor. Any Ractor may register an
|
|
address. The stored value must be a special constant, a shareable object,
|
|
or an unshareable object owned by the registering Ractor. If the address
|
|
holds another Ractor's unshareable object, the owning Ractor's GC cannot
|
|
see the registration and can free the stored object while the registered
|
|
address still refers to it. This can cause a use-after-free if the
|
|
registering Ractor attempts to use the Object stored.
|
|
|
|
If the address has process lifetime (a +static VALUE+), either register it
|
|
from the main Ractor or keep the stored values shareable.
|
|
|
|
Calling +Ractor#value+ on a Ractor moves its registrations to the calling
|
|
Ractor; otherwise they move to the main Ractor once the dead Ractor is
|
|
collected. If you rely on a Ractor inheriting another Ractor's registered
|
|
globals, call +Ractor#value+.
|
|
|
|
=== Prepare extconf.rb
|
|
|
|
If the file named extconf.rb exists, it will be executed to generate
|
|
Makefile.
|
|
|
|
extconf.rb is the file for checking compilation conditions etc. You
|
|
need to put
|
|
|
|
require 'mkmf'
|
|
|
|
at the top of the file. You can use the functions below to check
|
|
various conditions.
|
|
|
|
append_cppflags(array-of-flags[, opt]): append each flag to $CPPFLAGS if usable
|
|
append_cflags(array-of-flags[, opt]): append each flag to $CFLAGS if usable
|
|
append_ldflags(array-of-flags[, opt]): append each flag to $LDFLAGS if usable
|
|
have_macro(macro[, headers[, opt]]): check whether macro is defined
|
|
have_library(lib[, func[, headers[, opt]]]): check whether library containing function exists
|
|
find_library(lib[, func, *paths]): find library from paths
|
|
have_func(func[, headers[, opt]): check whether function exists
|
|
have_var(var[, headers[, opt]]): check whether variable exists
|
|
have_header(header[, preheaders[, opt]]): check whether header file exists
|
|
find_header(header, *paths): find header from paths
|
|
have_framework(fw): check whether framework exists (for MacOS X)
|
|
have_struct_member(type, member[, headers[, opt]]): check whether struct has member
|
|
have_type(type[, headers[, opt]]): check whether type exists
|
|
find_type(type, opt, *headers): check whether type exists in headers
|
|
have_const(const[, headers[, opt]]): check whether constant is defined
|
|
check_sizeof(type[, headers[, opts]]): check size of type
|
|
check_signedness(type[, headers[, opts]]): check signedness of type
|
|
convertible_int(type[, headers[, opts]]): find convertible integer type
|
|
find_executable(bin[, path]): find executable file path
|
|
create_header(header): generate configured header
|
|
create_makefile(target[, target_prefix]): generate Makefile
|
|
|
|
See MakeMakefile for full documentation of these functions.
|
|
|
|
The value of the variables below will affect the Makefile.
|
|
|
|
$CFLAGS: included in CFLAGS make variable (such as -O)
|
|
$CPPFLAGS: included in CPPFLAGS make variable (such as -I, -D)
|
|
$LDFLAGS: included in LDFLAGS make variable (such as -L)
|
|
$objs: list of object file names
|
|
|
|
Compiler/linker flags are not portable usually, you should use
|
|
+append_cppflags+, +append_cflags+ and +append_ldflags+ respectively
|
|
instead of appending the above variables directly.
|
|
|
|
Normally, the object files list is automatically generated by searching
|
|
source files, but you must define them explicitly if any sources will
|
|
be generated while building.
|
|
|
|
If a compilation condition is not fulfilled, you should not call
|
|
{create_makefile}[rdoc-ref:MakeMakefile#create_makefile]. The Makefile will not be generated,
|
|
compilation will not be done.
|
|
|
|
=== Prepare depend (Optional)
|
|
|
|
If the file named depend exists, Makefile will include that file to
|
|
check dependencies. You can make this file by invoking
|
|
|
|
% gcc -MM *.c > depend
|
|
|
|
It's harmless. Prepare it.
|
|
|
|
=== Generate Makefile
|
|
|
|
Try generating the Makefile by:
|
|
|
|
ruby extconf.rb
|
|
|
|
If the library should be installed under vendor_ruby directory
|
|
instead of site_ruby directory, use --vendor option as follows.
|
|
|
|
ruby extconf.rb --vendor
|
|
|
|
You don't need this step if you put the extension library under the ext
|
|
directory of the ruby source tree. In that case, compilation of the
|
|
interpreter will do this step for you.
|
|
|
|
=== Run make
|
|
|
|
Type
|
|
|
|
make
|
|
|
|
to compile your extension. You don't need this step either if you have
|
|
put the extension library under the ext directory of the ruby source tree.
|
|
|
|
=== Debug
|
|
|
|
You may need to rb_debug the extension. Extensions can be linked
|
|
statically by adding the directory name in the ext/Setup file so that
|
|
you can inspect the extension with the debugger.
|
|
|
|
=== Done! Now you have the extension library
|
|
|
|
You can do anything you want with your library. The author of Ruby
|
|
will not claim any restrictions on your code depending on the Ruby API.
|
|
Feel free to use, modify, distribute or sell your program.
|
|
|
|
== Appendix A. Ruby header and source files overview
|
|
|
|
=== Ruby header files
|
|
|
|
Everything under <tt>$repo_root/include/ruby</tt> is installed with
|
|
<tt>make install</tt>.
|
|
It should be included per <tt>#include <ruby.h></tt> from C extensions.
|
|
All symbols are public API with the exception of symbols prefixed with
|
|
+rbimpl_+ or +RBIMPL_+. They are implementation details and shouldn't
|
|
be used by C extensions.
|
|
|
|
Only <tt>$repo_root/include/ruby/*.h</tt> whose corresponding macros
|
|
are defined in the <tt>$repo_root/include/ruby.h</tt> header are
|
|
allowed to be <tt>#include</tt>-d by C extensions.
|
|
|
|
Header files under <tt>$repo_root/internal/</tt> or directly under the
|
|
root <tt>$repo_root/*.h</tt> are not make-installed.
|
|
They are internal headers with only internal APIs.
|
|
|
|
=== Ruby language core
|
|
|
|
class.c :: classes and modules
|
|
error.c :: exception classes and exception mechanism
|
|
gc.c :: memory management
|
|
load.c :: library loading
|
|
object.c :: objects
|
|
variable.c :: variables and constants
|
|
|
|
=== Ruby syntax parser
|
|
|
|
parse.y :: grammar definition
|
|
parse.c :: automatically generated from parse.y
|
|
defs/keywords :: reserved keywords
|
|
lex.c :: automatically generated from keywords
|
|
id.c :: pre-defined IDs
|
|
|
|
=== Ruby evaluator (a.k.a. YARV)
|
|
|
|
eval.c ::
|
|
eval_error.c ::
|
|
eval_jump.c ::
|
|
Evaluator
|
|
|
|
compile.c :: AST to VM instruction compiler
|
|
iseq.c :: implementation of VM::ISeq
|
|
|
|
thread.c ::
|
|
thread_win32.c ::
|
|
thread_pthread.c ::
|
|
thread management and context switching
|
|
|
|
vm.c ::
|
|
vm_dump.c ::
|
|
vm_eval.c ::
|
|
vm_exec.c ::
|
|
vm_insnhelper.c ::
|
|
vm_method.c ::
|
|
VM implementation
|
|
|
|
insns.def :: definition of VM instructions
|
|
defs/opt_insns_unif.def :: instruction unification
|
|
defs/opt_operand.def :: definitions for optimization
|
|
|
|
-> insn*.inc ::
|
|
-> opt*.inc ::
|
|
-> vm.inc ::
|
|
automatically generated
|
|
|
|
=== Regular expression engine (Onigumo)
|
|
|
|
regcomp.c :: compiler
|
|
regenc.c :: encodings
|
|
regerror.c :: error handling
|
|
regexec.c :: executer
|
|
regparse.c :: parser
|
|
regsyntax.c :: pre-defined syntax options
|
|
|
|
=== Utility functions
|
|
|
|
debug.c :: debug symbols for C debugger
|
|
dln.c :: dynamic loading
|
|
st.c :: general purpose hash table
|
|
strftime.c :: formatting times
|
|
util.c :: misc utilities
|
|
|
|
=== Ruby interpreter implementation
|
|
|
|
dmyext.c ::
|
|
dmydln.c ::
|
|
dmyencoding.c ::
|
|
for miniruby
|
|
|
|
id.c ::
|
|
inits.c ::
|
|
main.c ::
|
|
ruby.c ::
|
|
version.c ::
|
|
Ruby command
|
|
|
|
builtijns.c ::
|
|
gem_prelude.rb ::
|
|
prelude.rb ::
|
|
for Ruby code loaded at start up
|
|
|
|
=== Class library
|
|
|
|
array.c :: Array
|
|
bignum.c :: Integer (Bignum)
|
|
compar.c :: Comparable
|
|
complex.c :: Complex
|
|
cont.c :: Fiber, Continuation
|
|
dir.c :: Dir
|
|
enum.c :: Enumerable
|
|
enumerator.c :: Enumerator
|
|
file.c :: File
|
|
hash.c :: Hash
|
|
io.c :: IO
|
|
marshal.c :: Marshal
|
|
math.c :: Math
|
|
numeric.c :: Numeric, Integer (Fixnum), Float
|
|
pack.c :: Array#pack, String#unpack
|
|
proc.c :: Binding, Proc
|
|
process.c :: Process
|
|
random.c :: Random number generator
|
|
range.c :: Range
|
|
rational.c :: Rational
|
|
re.c :: Regexp, MatchData
|
|
signal.c :: Signal
|
|
sprintf.c :: String#sprintf
|
|
string.c :: String
|
|
struct.c :: Struct
|
|
symbol.c :: Symbol
|
|
time.c :: Time
|
|
|
|
defs/known_errors.def :: exception classes under Errno
|
|
-> known_errors.inc :: automatically generated
|
|
|
|
=== Multilingualization
|
|
|
|
encoding.c :: Encoding
|
|
transcode.c :: Encoding::Converter
|
|
enc/*.c :: encoding classes
|
|
enc/trans/* :: codepoint mapping tables
|
|
|
|
=== goruby interpreter implementation
|
|
|
|
goruby.c ::
|
|
golf_prelude.rb :: goruby specific libraries.
|
|
-> golf_prelude.c :: automatically generated
|
|
|
|
== Appendix B. Ruby extension API reference
|
|
|
|
=== Types
|
|
|
|
+VALUE+ ::
|
|
|
|
The type for the Ruby object. Actual structures are defined in ruby.h,
|
|
such as <tt>struct RString</tt>, etc. To refer the values in structures, use
|
|
casting macros like <tt>RSTRING(obj)</tt>.
|
|
|
|
=== Variables and constants
|
|
|
|
+Qnil+ ::
|
|
|
|
+nil+ object
|
|
|
|
+Qtrue+ ::
|
|
|
|
+true+ object (default true value)
|
|
|
|
+Qfalse+ ::
|
|
|
|
+false+ object
|
|
|
|
=== Checking VALUE types
|
|
|
|
<tt>RB_TYPE_P(value, type)</tt> ::
|
|
|
|
Is _value_ an internal _type_ (+T_NIL+, +T_FIXNUM+, etc.)?
|
|
|
|
<tt>TYPE(value)</tt> ::
|
|
|
|
Internal type (+T_NIL+, +T_FIXNUM+, etc.)
|
|
|
|
<tt>FIXNUM_P(value)</tt> ::
|
|
|
|
Is _value_ a Fixnum?
|
|
|
|
<tt>NIL_P(value)</tt> ::
|
|
|
|
Is _value_ +nil+?
|
|
|
|
<tt>RB_INTEGER_TYPE_P(value)</tt> ::
|
|
|
|
Is _value_ an Integer?
|
|
|
|
<tt>RB_FLOAT_TYPE_P(value)</tt> ::
|
|
|
|
Is _value_ a Float?
|
|
|
|
<tt>void Check_Type(VALUE value, int type)</tt> ::
|
|
|
|
Ensures _value_ is of the given internal _type_ or raises a TypeError
|
|
|
|
=== VALUE type conversion
|
|
|
|
<tt>FIX2INT(value)</tt>, <tt>INT2FIX(i)</tt> ::
|
|
|
|
Fixnum <-> integer
|
|
|
|
<tt>FIX2LONG(value)</tt>, <tt>LONG2FIX(l)</tt> ::
|
|
|
|
Fixnum <-> long
|
|
|
|
<tt>NUM2INT(value)</tt>, <tt>INT2NUM(i)</tt> ::
|
|
|
|
Numeric <-> integer
|
|
|
|
<tt>NUM2UINT(value)</tt>, <tt>UINT2NUM(ui)</tt> ::
|
|
|
|
Numeric <-> unsigned integer
|
|
|
|
<tt>NUM2LONG(value)</tt>, <tt>LONG2NUM(l)</tt> ::
|
|
|
|
Numeric <-> long
|
|
|
|
<tt>NUM2ULONG(value)</tt>, <tt>ULONG2NUM(ul)</tt> ::
|
|
|
|
Numeric <-> unsigned long
|
|
|
|
<tt>NUM2LL(value)</tt>, <tt>LL2NUM(ll)</tt> ::
|
|
|
|
Numeric <-> long long
|
|
|
|
<tt>NUM2ULL(value)</tt>, <tt>ULL2NUM(ull)</tt> ::
|
|
|
|
Numeric <-> unsigned long long
|
|
|
|
<tt>NUM2OFFT(value)</tt>, <tt>OFFT2NUM(off)</tt> ::
|
|
|
|
Numeric <-> off_t
|
|
|
|
<tt>NUM2SIZET(value)</tt>, <tt>SIZET2NUM(size)</tt> ::
|
|
|
|
Numeric <-> size_t
|
|
|
|
<tt>NUM2SSIZET(value)</tt>, <tt>SSIZET2NUM(ssize)</tt> ::
|
|
|
|
Numeric <-> ssize_t
|
|
|
|
<tt>rb_integer_pack(value, words, numwords, wordsize, nails, flags)</tt>, <tt>rb_integer_unpack(words, numwords, wordsize, nails, flags)</tt> ::
|
|
|
|
Numeric <-> Arbitrary size integer buffer
|
|
|
|
<tt>NUM2DBL(value)</tt> ::
|
|
|
|
Numeric -> double
|
|
|
|
<tt>rb_float_new(f)</tt> ::
|
|
|
|
double -> Float
|
|
|
|
<tt>RSTRING_LEN(str)</tt> ::
|
|
|
|
String -> length of String data in bytes
|
|
|
|
<tt>RSTRING_PTR(str)</tt> ::
|
|
|
|
String -> pointer to String data
|
|
Note that the result pointer may not be NUL-terminated
|
|
|
|
<tt>StringValue(value)</tt> ::
|
|
|
|
Object with <tt>#to_str</tt> -> String
|
|
|
|
<tt>StringValuePtr(value)</tt> ::
|
|
|
|
Object with <tt>#to_str</tt> -> pointer to String data
|
|
|
|
<tt>StringValueCStr(value)</tt> ::
|
|
|
|
Object with <tt>#to_str</tt> -> pointer to String data without NUL bytes
|
|
It is guaranteed that the result data is NUL-terminated
|
|
|
|
<tt>rb_str_new2(s)</tt> ::
|
|
|
|
char * -> String
|
|
|
|
=== Defining classes and modules
|
|
|
|
<tt>VALUE rb_define_class(const char *name, VALUE super)</tt> ::
|
|
|
|
Defines a Ruby class as a subclass of _super_ with named specified by
|
|
_name_ at the top-level.
|
|
|
|
<tt>VALUE rb_define_class_under(VALUE module, const char *name, VALUE super)</tt> ::
|
|
|
|
Defines a Ruby class as a subclass of _super_ with named specified by
|
|
_name_ under the <i>module</i>'s namespace.
|
|
|
|
<tt>VALUE rb_define_module(const char *name)</tt> ::
|
|
|
|
Defines a Ruby module with named specified by _name_ at the top-level.
|
|
|
|
<tt>VALUE rb_define_module_under(VALUE module, const char *name)</tt> ::
|
|
|
|
Defines a Ruby module with named specified by _name_ under the
|
|
<i>module</i>'s namespace.
|
|
|
|
<tt>void rb_include_module(VALUE klass, VALUE module)</tt> ::
|
|
|
|
Includes _module_ into _class_. If _class_ already includes it, just
|
|
ignored.
|
|
|
|
<tt>void rb_extend_object(VALUE object, VALUE module)</tt> ::
|
|
|
|
Extend the _object_ with the <i>module</i>'s attributes.
|
|
|
|
=== Defining global variables
|
|
|
|
<tt>void rb_define_variable(const char *name, VALUE *var)</tt> ::
|
|
|
|
Defines a global variable _name_ which is shared between C and Ruby. If
|
|
_name_ does not start with +$+, it is prefixed automatically. If that
|
|
variable name contains a character which is not allowed a global
|
|
variable, that variable can't be seen from Ruby programs.
|
|
|
|
<tt>void rb_define_readonly_variable(const char *name, VALUE *var)</tt> ::
|
|
|
|
Defines a read-only global variable. Works just like
|
|
<tt>rb_define_variable()</tt>, except the defined variable is read-only.
|
|
|
|
<tt>void rb_define_virtual_variable(const char *name, VALUE (*getter)(), void (*setter)())</tt> ::
|
|
|
|
Defines a virtual variable, whose behavior is defined by a pair of C
|
|
functions. The _getter_ function is called when the variable is
|
|
referenced. The _setter_ function is called when the variable is set to a
|
|
value.
|
|
|
|
These functions are the same as +rb_define_hooked_variable+, but the
|
|
_var_ argument is meaningless.
|
|
|
|
<tt>void rb_define_hooked_variable(const char *name, VALUE *var, VALUE (*getter)(), void (*setter)())</tt> ::
|
|
|
|
Defines hooked variable. It's a virtual variable with a C variable.
|
|
The _getter_ is called as
|
|
|
|
VALUE getter(ID id, VALUE *var)
|
|
|
|
returning a new value. The _setter_ is called as
|
|
|
|
void setter(VALUE val, ID id, VALUE *var)
|
|
|
|
_id_ is the ID interned from _name_, and _var_ is the argument itself.
|
|
_val_ is the value to be set.
|
|
|
|
<tt>void rb_global_variable(VALUE *var)</tt> ::
|
|
|
|
Tells GC to protect C global variable, which holds Ruby value to be marked.
|
|
The registration belongs to the calling Ractor: the stored value must be
|
|
a special constant, a shareable object, or an unshareable object owned by
|
|
the registering Ractor.
|
|
|
|
<tt>void rb_gc_register_mark_object(VALUE object)</tt> ::
|
|
|
|
Tells GC to protect the _object_, which may not be referenced anywhere.
|
|
|
|
=== Constant definition
|
|
|
|
<tt>void rb_define_const(VALUE klass, const char *name, VALUE val)</tt> ::
|
|
|
|
Defines a new constant under the class/module.
|
|
|
|
<tt>void rb_define_global_const(const char *name, VALUE val)</tt> ::
|
|
|
|
Defines a global constant. This is just the same as
|
|
|
|
rb_define_const(rb_cObject, name, val)
|
|
|
|
=== \Method definition
|
|
|
|
<tt>rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)</tt> ::
|
|
|
|
Defines a method for the class. func is the function pointer. argc
|
|
is the number of arguments. if _argc_ is -1, the function will receive
|
|
3 arguments: _argc_, _argv_, and _self_. if _argc_ is -2, the function will
|
|
receive 2 arguments, _self_ and _args_, where _args_ is a Ruby array of
|
|
the method arguments.
|
|
|
|
<tt>rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)</tt> ::
|
|
|
|
Defines a private method for the class. Arguments are same as
|
|
<tt>rb_define_method()</tt>.
|
|
|
|
<tt>rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)</tt> ::
|
|
|
|
Defines a singleton method. Arguments are same as <tt>rb_define_method()</tt>.
|
|
|
|
<tt>rb_check_arity(int argc, int min, int max)</tt> ::
|
|
|
|
Check the number of arguments, _argc_ is in the range of +min..max+. If
|
|
_max_ is +UNLIMITED_ARGUMENTS+, upper bound is not checked. If _argc_ is
|
|
out of bounds, an ArgumentError will be raised.
|
|
|
|
<tt>rb_scan_args(int argc, VALUE *argv, const char *fmt, ...)</tt> ::
|
|
|
|
Retrieve argument from _argc_ and _argv_ to given VALUE references
|
|
according to the format string _fmt_. The format can be described in ABNF
|
|
as follows:
|
|
|
|
scan-arg-spec := param-arg-spec [keyword-arg-spec] [block-arg-spec]
|
|
|
|
param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec /
|
|
pre-opt-post-arg-spec
|
|
pre-arg-spec := num-of-leading-mandatory-args [num-of-optional-args]
|
|
post-arg-spec := sym-for-variable-length-args
|
|
[num-of-trailing-mandatory-args]
|
|
pre-opt-post-arg-spec := num-of-leading-mandatory-args num-of-optional-args
|
|
num-of-trailing-mandatory-args
|
|
keyword-arg-spec := sym-for-keyword-arg
|
|
block-arg-spec := sym-for-block-arg
|
|
|
|
num-of-leading-mandatory-args := DIGIT ; The number of leading
|
|
; mandatory arguments
|
|
num-of-optional-args := DIGIT ; The number of optional
|
|
; arguments
|
|
sym-for-variable-length-args := "*" ; Indicates that variable
|
|
; length arguments are
|
|
; captured as a ruby array
|
|
num-of-trailing-mandatory-args := DIGIT ; The number of trailing
|
|
; mandatory arguments
|
|
sym-for-keyword-arg := ":" ; Indicates that keyword
|
|
; argument captured as a hash.
|
|
; If keyword arguments are not
|
|
; provided, returns nil.
|
|
sym-for-block-arg := "&" ; Indicates that an iterator
|
|
; block should be captured if
|
|
; given
|
|
|
|
For example, "12" means that the method requires at least one
|
|
argument, and at most receives three (1+2) arguments. So, the format
|
|
string must be followed by three variable references, which are to be
|
|
assigned to captured arguments. For omitted arguments, variables are
|
|
set to +Qnil+. NULL can be put in place of a variable reference, which
|
|
means the corresponding captured argument(s) should be just dropped.
|
|
|
|
The number of given arguments, excluding an option hash or iterator
|
|
block, is returned.
|
|
|
|
<tt>rb_scan_args_kw(int kw_splat, int argc, VALUE *argv, const char *fmt, ...)</tt> ::
|
|
|
|
The same as +rb_scan_args+, except the _kw_splat_ argument specifies whether
|
|
keyword arguments are provided (instead of being determined by the call
|
|
from Ruby to the C function). _kw_splat_ should be one of the following
|
|
values:
|
|
|
|
+RB_SCAN_ARGS_PASS_CALLED_KEYWORDS+ :: Same behavior as +rb_scan_args+.
|
|
+RB_SCAN_ARGS_KEYWORDS+ :: The final argument should be a hash treated as
|
|
keywords.
|
|
+RB_SCAN_ARGS_LAST_HASH_KEYWORDS+ :: Treat a final argument as keywords if it
|
|
is a hash, and not as keywords otherwise.
|
|
|
|
<tt>int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)</tt> ::
|
|
|
|
Retrieves argument VALUEs bound to keywords, which directed by _table_
|
|
into _values_, deleting retrieved entries from _keyword_hash_ along
|
|
the way. First _required_ number of IDs referred by _table_ are
|
|
mandatory, and succeeding _optional_ (<tt>- optional - 1</tt> if
|
|
_optional_ is negative) number of IDs are optional. If a
|
|
mandatory key is not contained in _keyword_hash_, raises "missing
|
|
keyword" ArgumentError. If an optional key is not present in
|
|
_keyword_hash_, the corresponding element in _values_ is set to +Qundef+.
|
|
If _optional_ is negative, rest of _keyword_hash_ are ignored, otherwise
|
|
raises "unknown keyword" ArgumentError.
|
|
|
|
Be warned, handling keyword arguments in the C API is less efficient
|
|
than handling them in Ruby. Consider using a Ruby wrapper method
|
|
around a non-keyword C function.
|
|
ref: https://bugs.ruby-lang.org/issues/11339
|
|
|
|
<tt>VALUE rb_extract_keywords(VALUE *original_hash)</tt> ::
|
|
|
|
Extracts pairs whose key is a symbol into a new hash from a hash
|
|
object referred by _original_hash_. If the original hash contains
|
|
non-symbol keys, then they are copied to another hash and the new hash
|
|
is stored through _original_hash_, else 0 is stored.
|
|
|
|
=== Invoking Ruby method
|
|
|
|
<tt>VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)</tt> ::
|
|
|
|
Invokes a method specified by _mid_ on _recv_. To retrieve _mid_
|
|
from a method name, use <tt>rb_intern()</tt>. Able to call even
|
|
private/protected methods. Arguments after _narg_ are passe to the
|
|
method, and _narg_ should be the number of arguments.
|
|
|
|
<tt>VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)</tt> ::
|
|
<tt>VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv)</tt> ::
|
|
|
|
Invokes a method, passing arguments as an array of values.
|
|
Able to call even private/protected methods.
|
|
|
|
<tt>VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, VALUE *argv, int kw_splat)</tt> ::
|
|
|
|
Same as rb_funcallv, using _kw_splat_ to determine whether keyword
|
|
arguments are passed.
|
|
|
|
<tt>VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, VALUE *argv)</tt> ::
|
|
|
|
Invokes a method, passing arguments as an array of values.
|
|
Able to call only public methods.
|
|
|
|
<tt>VALUE rb_funcallv_public_kw(VALUE recv, ID mid, int argc, VALUE *argv, int kw_splat)</tt> ::
|
|
|
|
Same as +rb_funcallv_public+, using _kw_splat_ to determine whether keyword
|
|
arguments are passed.
|
|
|
|
<tt>VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE* argv)</tt> ::
|
|
|
|
Same as +rb_funcallv_public+, except is passes the currently active block as
|
|
the block when calling the method.
|
|
|
|
<tt>VALUE rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE* argv, int kw_splat)</tt> ::
|
|
|
|
Same as +rb_funcall_passing_block+, using _kw_splat_ to determine whether
|
|
keyword arguments are passed.
|
|
|
|
<tt>VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval)</tt> ::
|
|
|
|
Same as +rb_funcallv_public+, except _passed_procval_ specifies the block to
|
|
pass to the method.
|
|
|
|
<tt>VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval, int kw_splat)</tt> ::
|
|
|
|
Same as +rb_funcall_with_block+, using _kw_splat_ to determine whether
|
|
keyword arguments are passed.
|
|
|
|
<tt>VALUE rb_eval_string(const char *str)</tt> ::
|
|
|
|
Compiles and executes the string as a Ruby program.
|
|
|
|
<tt>ID rb_intern(const char *name)</tt> ::
|
|
|
|
Returns ID corresponding to the _name_.
|
|
|
|
<tt>char *rb_id2name(ID id)</tt> ::
|
|
|
|
Returns the name corresponding ID.
|
|
|
|
<tt>char *rb_class2name(VALUE klass)</tt> ::
|
|
|
|
Returns the name of the class.
|
|
|
|
<tt>int rb_respond_to(VALUE obj, ID id)</tt> ::
|
|
|
|
Returns true if the object responds to the message specified by _id_.
|
|
|
|
=== Instance variables
|
|
|
|
<tt>VALUE rb_iv_get(VALUE obj, const char *name)</tt> ::
|
|
|
|
Retrieve the value of the instance variable. If the name is not
|
|
prefixed by <code>@</code>, that variable shall be inaccessible from Ruby.
|
|
|
|
<tt>VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)</tt> ::
|
|
|
|
Sets the value of the instance variable.
|
|
|
|
=== Control structure
|
|
|
|
<tt>VALUE rb_block_call(VALUE recv, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2)</tt> ::
|
|
|
|
Calls a method on the _recv_, with the method name specified by the
|
|
symbol _mid_, with _argc_ arguments in _argv_, supplying _func_ as the
|
|
block. When _func_ is called as the block, it will receive the value
|
|
from +yield+ as the first argument, and _data2_ as the second argument.
|
|
When yielded with multiple values (in C, <tt>rb_yield_values()</tt>,
|
|
<tt>rb_yield_values2()</tt> and <tt>rb_yield_splat()</tt>), _data2_ is
|
|
packed as an Array, whereas yielded values can be gotten via
|
|
_argc_/_argv_ of the third/fourth arguments.
|
|
|
|
<tt>VALUE rb_block_call_kw(VALUE recv, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2, int kw_splat)</tt> ::
|
|
|
|
Same as +rb_funcall_with_block+, using _kw_splat_ to determine whether
|
|
keyword arguments are passed.
|
|
|
|
\[OBSOLETE] <tt>VALUE rb_iterate(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2)</tt> ::
|
|
|
|
Calls the function _func1_, supplying _func2_ as the block. _func1_ will be
|
|
called with the argument _arg1_. _func2_ receives the value from +yield+ as
|
|
the first argument, _arg2_ as the second argument.
|
|
|
|
When +rb_iterate+ is used in 1.9, _func1_ has to call some Ruby-level method.
|
|
This function is obsolete since 1.9; use +rb_block_call+ instead.
|
|
|
|
<tt>VALUE rb_yield(VALUE val)</tt> ::
|
|
|
|
Yields _val_ as a single argument to the block.
|
|
|
|
<tt>VALUE rb_yield_values(int n, ...)</tt> ::
|
|
|
|
Yields _n_ number of arguments to the block, using one C argument per Ruby
|
|
argument.
|
|
|
|
<tt>VALUE rb_yield_values2(int n, VALUE *argv)</tt> ::
|
|
|
|
Yields _n_ number of arguments to the block, with all Ruby arguments in the
|
|
C argv array.
|
|
|
|
<tt>VALUE rb_yield_values_kw(int n, VALUE *argv, int kw_splat)</tt> ::
|
|
|
|
Same as +rb_yield_values2+, using _kw_splat_ to determine whether
|
|
keyword arguments are passed.
|
|
|
|
<tt>VALUE rb_yield_splat(VALUE args)</tt> ::
|
|
|
|
Same as +rb_yield_values2+, except arguments are specified by the Ruby
|
|
array +args+.
|
|
|
|
<tt>VALUE rb_yield_splat_kw(VALUE args, int kw_splat)</tt> ::
|
|
|
|
Same as +rb_yield_splat+, using _kw_splat_ to determine whether
|
|
keyword arguments are passed.
|
|
|
|
<tt>VALUE rb_rescue(VALUE (*func1)(ANYARGS), VALUE arg1, VALUE (*func2)(ANYARGS), VALUE arg2)</tt> ::
|
|
|
|
Calls the function _func1_, with _arg1_ as the argument. If an exception
|
|
occurs during _func1_, it calls _func2_ with _arg2_ as the first argument
|
|
and the exception object as the second argument. The return value of
|
|
<tt>rb_rescue()</tt> is the return value from _func1_ if no exception
|
|
occurs, from _func2_ otherwise.
|
|
|
|
<tt>VALUE rb_ensure(VALUE (*func1)(ANYARGS), VALUE arg1, VALUE (*func2)(ANYARGS), VALUE arg2)</tt> ::
|
|
|
|
Calls the function _func1_ with _arg1_ as the argument, then calls _func2_
|
|
with _arg2_ if execution terminated. The return value from
|
|
<tt>rb_ensure()</tt> is that of _func1 when no exception occurred.
|
|
|
|
<tt>VALUE rb_protect(VALUE (*func) (VALUE), VALUE arg, int *state)</tt> ::
|
|
|
|
Calls the function _func_ with _arg_ as the argument. If no exception
|
|
occurred during _func_, it returns the result of _func_ and
|
|
<tt>*state</tt> is zero.
|
|
Otherwise, it returns +Qnil+ and sets <tt>*state</tt> to nonzero. If
|
|
state is NULL, it is not set in both cases. You have to clear the error
|
|
info with <tt>rb_set_errinfo(Qnil)</tt> when ignoring the caught exception.
|
|
|
|
<tt>void rb_jump_tag(int state)</tt> ::
|
|
|
|
Continues the exception caught by <tt>rb_protect()</tt> and <tt>rb_eval_string_protect()</tt>.
|
|
_state_ must be the returned value from those functions. This function
|
|
never return to the caller.
|
|
|
|
<tt>void rb_iter_break()</tt> ::
|
|
|
|
Exits from the current innermost block. This function never return to
|
|
the caller.
|
|
|
|
<tt>void rb_iter_break_value(VALUE value)</tt> ::
|
|
|
|
Exits from the current innermost block with the value. The block will
|
|
return the given argument value. This function never return to the
|
|
caller.
|
|
|
|
=== Exceptions and errors
|
|
|
|
<tt>void rb_warn(const char *fmt, ...)</tt> ::
|
|
|
|
Prints a warning message according to a printf-like format.
|
|
|
|
<tt>void rb_warning(const char *fmt, ...)</tt> ::
|
|
|
|
Prints a warning message according to a printf-like format, if
|
|
_$VERBOSE_ is true.
|
|
|
|
<tt>void rb_raise(rb_eRuntimeError, const char *fmt, ...)</tt> ::
|
|
|
|
Raises RuntimeError. The _fmt_ is a format string just like printf().
|
|
|
|
<tt>void rb_raise(VALUE exception, const char *fmt, ...)</tt> ::
|
|
|
|
Raises a class exception. The _fmt_ is a format string just like printf().
|
|
|
|
<tt>void rb_fatal(const char *fmt, ...)</tt> ::
|
|
|
|
Raises a fatal error, terminates the interpreter. No exception handling
|
|
will be done for fatal errors, but ensure blocks will be executed.
|
|
|
|
<tt>void rb_bug(const char *fmt, ...)</tt> ::
|
|
|
|
Terminates the interpreter immediately. This function should be
|
|
called under the situation caused by the bug in the interpreter. No
|
|
exception handling nor ensure execution will be done.
|
|
|
|
Note: In the format string, <tt>"%"PRIsVALUE</tt> can be used for Object#to_s
|
|
(or Object#inspect if <tt>+</tt> flag is set) output (and related argument
|
|
must be a VALUE). Since it conflicts with <tt>"%i"</tt>, for integers in
|
|
format strings, use <tt>"%d"</tt>.
|
|
|
|
=== Threading
|
|
|
|
As of Ruby 1.9, Ruby supports native 1:1 threading with one kernel
|
|
thread per Ruby Thread object. Currently, there is a GVL (Global VM Lock)
|
|
which prevents simultaneous execution of Ruby code which may be released
|
|
by the +rb_thread_call_without_gvl+ and +rb_thread_call_without_gvl2+ functions.
|
|
These functions are tricky-to-use and documented in thread.c; do not
|
|
use them before reading comments in thread.c.
|
|
|
|
<tt>void rb_thread_schedule(void)</tt> ::
|
|
|
|
Give the scheduler a hint to pass execution to another thread.
|
|
|
|
=== Input/Output (IO) on a single file descriptor
|
|
|
|
<tt>int rb_io_wait_readable(int fd)</tt> ::
|
|
|
|
Wait indefinitely for the given FD to become readable, allowing other
|
|
threads to be scheduled. Returns a true value if a read may be
|
|
performed, false if there is an unrecoverable error.
|
|
|
|
<tt>int rb_io_wait_writable(int fd)</tt> ::
|
|
|
|
Like +rb_io_wait_readable+, but for writability.
|
|
|
|
<tt>int rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)</tt> ::
|
|
|
|
Allows waiting on a single FD for one or multiple events with a
|
|
specified timeout.
|
|
|
|
_events_ is a mask of any combination of the following values:
|
|
|
|
+RB_WAITFD_IN+ :: wait for readability of normal data
|
|
+RB_WAITFD_OUT+ :: wait for writability
|
|
+RB_WAITFD_PRI+ :: wait for readability of urgent data
|
|
|
|
Use a NULL _timeout_ to wait indefinitely.
|
|
|
|
=== I/O multiplexing
|
|
|
|
Ruby supports I/O multiplexing based on the select(2) system call.
|
|
The Linux select_tut(2) manpage
|
|
<http://man7.org/linux/man-pages/man2/select_tut.2.html>
|
|
provides a good overview on how to use select(2), and the Ruby API has
|
|
analogous functions and data structures to the well-known select API.
|
|
Understanding of select(2) is required to understand this section.
|
|
|
|
<tt>typedef struct rb_fdset_t</tt> ::
|
|
|
|
The data structure which wraps the fd_set bitmap used by select(2).
|
|
This allows Ruby to use FD sets larger than that allowed by
|
|
historic limitations on modern platforms.
|
|
|
|
<tt>void rb_fd_init(rb_fdset_t *)</tt> ::
|
|
|
|
Initializes the +rb_fdset_t+, it must be initialized before other rb_fd_*
|
|
operations. Analogous to calling malloc(3) to allocate an fd_set.
|
|
|
|
<tt>void rb_fd_term(rb_fdset_t *)</tt> ::
|
|
|
|
Destroys the +rb_fdset_t+, releasing any memory and resources it used.
|
|
It must be reinitialized using +rb_fd_init+ before future use.
|
|
Analogous to calling free(3) to release memory for an fd_set.
|
|
|
|
<tt>void rb_fd_zero(rb_fdset_t *)</tt> ::
|
|
|
|
Clears all FDs from the +rb_fdset_t+, analogous to FD_ZERO(3).
|
|
|
|
<tt>void rb_fd_set(int fd, rb_fdset_t *)</tt> ::
|
|
|
|
Adds a given FD in the +rb_fdset_t+, analogous to FD_SET(3).
|
|
|
|
<tt>void rb_fd_clr(int fd, rb_fdset_t *)</tt> ::
|
|
|
|
Removes a given FD from the +rb_fdset_t+, analogous to FD_CLR(3).
|
|
|
|
<tt>int rb_fd_isset(int fd, const rb_fdset_t *)</tt> ::
|
|
|
|
Returns true if a given _fd_ is set in the +rb_fdset_t+, false if not.
|
|
Analogous to FD_ISSET(3).
|
|
|
|
<tt>int rb_thread_fd_select(int nfds, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout)</tt> ::
|
|
|
|
Analogous to the select(2) system call, but allows other Ruby
|
|
threads to be scheduled while waiting.
|
|
|
|
When only waiting on a single FD, favor +rb_io_wait_readable+,
|
|
+rb_io_wait_writable+, or +rb_wait_for_single_fd+ functions since
|
|
they can be optimized for specific platforms (currently, only Linux).
|
|
|
|
=== Initialize and start the interpreter
|
|
|
|
The embedding API functions are below (not needed for extension libraries):
|
|
|
|
<tt>void ruby_init()</tt> ::
|
|
|
|
Initializes the interpreter.
|
|
|
|
<tt>void *ruby_options(int argc, char **argv)</tt> ::
|
|
|
|
Process command line arguments for the interpreter.
|
|
And compiles the Ruby source to execute.
|
|
It returns an opaque pointer to the compiled source
|
|
or an internal special value.
|
|
|
|
<tt>int ruby_run_node(void *n)</tt> ::
|
|
|
|
Runs the given compiled source and exits this process.
|
|
It returns EXIT_SUCCESS if successfully runs the source.
|
|
Otherwise, it returns other value.
|
|
|
|
<tt>void ruby_script(char *name)</tt> ::
|
|
|
|
Specifies the name of the script (_$0_).
|
|
|
|
=== Hooks for the interpreter events
|
|
|
|
<tt>void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)</tt> ::
|
|
|
|
Adds a hook function for the specified interpreter events.
|
|
events should be OR'ed value of:
|
|
|
|
RUBY_EVENT_LINE
|
|
RUBY_EVENT_CLASS
|
|
RUBY_EVENT_END
|
|
RUBY_EVENT_CALL
|
|
RUBY_EVENT_RETURN
|
|
RUBY_EVENT_C_CALL
|
|
RUBY_EVENT_C_RETURN
|
|
RUBY_EVENT_RAISE
|
|
RUBY_EVENT_ALL
|
|
|
|
The definition of rb_event_hook_func_t is below:
|
|
|
|
typedef void (*rb_event_hook_func_t)(rb_event_t event, VALUE data,
|
|
VALUE self, ID id, VALUE klass)
|
|
|
|
The third argument _data_ to <code>rb_add_event_hook()</code> is passed to the hook
|
|
function as the second argument, which was the pointer to the current
|
|
NODE in 1.8. See +RB_EVENT_HOOKS_HAVE_CALLBACK_DATA+ below.
|
|
|
|
<tt>int rb_remove_event_hook(rb_event_hook_func_t func)</tt> ::
|
|
|
|
Removes the specified hook function.
|
|
|
|
=== Memory usage
|
|
|
|
<tt>void rb_gc_adjust_memory_usage(ssize_t diff)</tt> ::
|
|
|
|
Adjusts the amount of registered external memory. You can tell GC how
|
|
much memory is used by an external library by this function. Calling
|
|
this function with positive _diff_ means the memory usage is increased;
|
|
new memory block is allocated or a block is reallocated as larger
|
|
size. Calling this function with negative _diff_ means the memory usage
|
|
is decreased; a memory block is freed or a block is reallocated as
|
|
smaller size. This function may trigger the GC.
|
|
|
|
=== Macros for compatibility
|
|
|
|
Some macros to check API compatibilities are available by default.
|
|
|
|
+NORETURN_STYLE_NEW+ ::
|
|
|
|
Means that +NORETURN+ macro is functional style instead of prefix.
|
|
|
|
+HAVE_RB_DEFINE_ALLOC_FUNC+ ::
|
|
|
|
Means that function <tt>rb_define_alloc_func()</tt> is provided, that means the
|
|
allocation framework is used. This is the same as the result of
|
|
<tt>have_func("rb_define_alloc_func", "ruby.h")</tt>.
|
|
|
|
+HAVE_RB_REG_NEW_STR+ ::
|
|
|
|
Means that function <tt>rb_reg_new_str()</tt> is provided, that creates Regexp
|
|
object from String object. This is the same as the result of
|
|
<tt>have_func("rb_reg_new_str", "ruby.h")</tt>.
|
|
|
|
+HAVE_RB_IO_T+ ::
|
|
|
|
Means that type +rb_io_t+ is provided.
|
|
|
|
+HAVE_RB_LEN_T+ ::
|
|
|
|
Means that types +rb_len_t+ and +rb_ulen_t+ are provided, along with the
|
|
macros for them such as +LEN2NUM+, +NUM2LEN+ and +PRIdLEN+.
|
|
|
|
+USE_SYMBOL_AS_METHOD_NAME+ ::
|
|
|
|
Means that Symbols will be returned as method names, e.g.,
|
|
Module#methods, \#singleton_methods and so on.
|
|
|
|
<tt>HAVE_RUBY_*_H</tt> ::
|
|
|
|
Defined in ruby.h and means corresponding header is available. For
|
|
instance, when +HAVE_RUBY_ST_H+ is defined you should use ruby/st.h not
|
|
mere st.h.
|
|
|
|
Header files corresponding to these macros may be <tt>#include</tt>
|
|
directly from extension libraries.
|
|
|
|
+RB_EVENT_HOOKS_HAVE_CALLBACK_DATA+ ::
|
|
|
|
Means that <code>rb_add_event_hook()</code> takes the third argument _data_, to be
|
|
passed to the given event hook function.
|
|
|
|
=== Defining backward compatible macros for keyword argument functions
|
|
|
|
Most ruby C extensions are designed to support multiple Ruby versions.
|
|
In order to correctly support Ruby 2.7+ in regards to keyword
|
|
argument separation, C extensions need to use <code>*_kw</code>
|
|
functions. However, these functions do not exist in Ruby 2.6 and
|
|
below, so in those cases macros should be defined to allow you to use
|
|
the same code on multiple Ruby versions. Here are example macros
|
|
you can use in extensions that support Ruby 2.6 (or below) when using
|
|
the <code>*_kw</code> functions introduced in Ruby 2.7.
|
|
|
|
#ifndef RB_PASS_KEYWORDS
|
|
/* Only define macros on Ruby <2.7 */
|
|
#define rb_funcallv_kw(o, m, c, v, kw) rb_funcallv(o, m, c, v)
|
|
#define rb_funcallv_public_kw(o, m, c, v, kw) rb_funcallv_public(o, m, c, v)
|
|
#define rb_funcall_passing_block_kw(o, m, c, v, kw) rb_funcall_passing_block(o, m, c, v)
|
|
#define rb_funcall_with_block_kw(o, m, c, v, b, kw) rb_funcall_with_block(o, m, c, v, b)
|
|
#define rb_scan_args_kw(kw, c, v, s, ...) rb_scan_args(c, v, s, __VA_ARGS__)
|
|
#define rb_call_super_kw(c, v, kw) rb_call_super(c, v)
|
|
#define rb_yield_values_kw(c, v, kw) rb_yield_values2(c, v)
|
|
#define rb_yield_splat_kw(a, kw) rb_yield_splat(a)
|
|
#define rb_block_call_kw(o, m, c, v, f, p, kw) rb_block_call(o, m, c, v, f, p)
|
|
#define rb_fiber_resume_kw(o, c, v, kw) rb_fiber_resume(o, c, v)
|
|
#define rb_fiber_yield_kw(c, v, kw) rb_fiber_yield(c, v)
|
|
#define rb_enumeratorize_with_size_kw(o, m, c, v, f, kw) rb_enumeratorize_with_size(o, m, c, v, f)
|
|
#define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \
|
|
rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \
|
|
(argc), (argv), (size_fn))
|
|
#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \
|
|
if (!rb_block_given_p()) \
|
|
return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \
|
|
} while (0)
|
|
#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0)
|
|
#define rb_check_funcall_kw(o, m, c, v, kw) rb_check_funcall(o, m, c, v)
|
|
#define rb_obj_call_init_kw(o, c, v, kw) rb_obj_call_init(o, c, v)
|
|
#define rb_class_new_instance_kw(c, v, k, kw) rb_class_new_instance(c, v, k)
|
|
#define rb_proc_call_kw(p, a, kw) rb_proc_call(p, a)
|
|
#define rb_proc_call_with_block_kw(p, c, v, b, kw) rb_proc_call_with_block(p, c, v, b)
|
|
#define rb_method_call_kw(c, v, m, kw) rb_method_call(c, v, m)
|
|
#define rb_method_call_with_block_kw(c, v, m, b, kw) rb_method_call_with_block(c, v, m, b)
|
|
#define rb_eval_cmd_kw(c, a, kw) rb_eval_cmd(c, a, 0)
|
|
#endif
|
|
|
|
== Appendix C. Functions available for use in extconf.rb
|
|
|
|
See documentation for {mkmf}[rdoc-ref:MakeMakefile].
|
|
|
|
== Appendix D. Generational GC
|
|
|
|
Ruby 2.1 introduced a generational garbage collector (called RGenGC).
|
|
RGenGC (mostly) keeps compatibility.
|
|
|
|
Generally, the use of the technique called write barriers is required in
|
|
extension libraries for {generational GC
|
|
}[https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29].
|
|
RGenGC works fine without write barriers in extension libraries.
|
|
|
|
If your library adheres to the following tips, performance can be further
|
|
improved. Especially, the "{Don't touch pointers
|
|
directly}[rdoc-ref:@Don-27t+touch+pointers+directly]" section is important.
|
|
|
|
=== Incompatibility
|
|
|
|
You can't write <tt>RBASIC(obj)->klass</tt> field directly because it is
|
|
const value now.
|
|
|
|
Basically you should not write this field because MRI expects it to be
|
|
an immutable field, but if you want to do it in your extension you can
|
|
use the following functions:
|
|
|
|
<tt>VALUE rb_obj_hide(VALUE obj)</tt> ::
|
|
|
|
Clear +RBasic::klass+ field. The object will be an internal object.
|
|
ObjectSpace::each_object can't find this object.
|
|
|
|
<tt>VALUE rb_obj_reveal(VALUE obj, VALUE klass)</tt> ::
|
|
|
|
Reset +RBasic::klass+ to be _klass_.
|
|
We expect the _klass_ is hidden class by <tt>rb_obj_hide()</tt>.
|
|
|
|
=== Write barriers
|
|
|
|
RGenGC doesn't require write barriers to support generational GC.
|
|
However, caring about write barrier can improve the performance of
|
|
RGenGC. Please check the following tips.
|
|
|
|
==== Don't touch pointers directly
|
|
|
|
In MRI (include/ruby/ruby.h), some macros acquire pointers to the
|
|
internal data structures such as <tt>RARRAY_PTR()</tt>,
|
|
<tt>RSTRUCT_PTR()</tt> and so on.
|
|
|
|
DO NOT USE THESE MACROS and instead use the corresponding C-APIs such as
|
|
<tt>rb_ary_aref()</tt>, <tt>rb_ary_store()</tt> and so on.
|
|
|
|
==== Consider whether to insert write barriers
|
|
|
|
You don't need to care about write barriers if you only use built-in
|
|
types.
|
|
|
|
If you support +T_DATA+ objects, you may consider using write barriers.
|
|
|
|
Inserting write barriers into +T_DATA+ objects only works with the
|
|
following type objects: (a) long-lived objects, (b) when a huge number
|
|
of objects are generated and \(c) container-type objects that have
|
|
references to other objects. If your extension provides such a type of
|
|
+T_DATA+ objects, consider inserting write barriers.
|
|
|
|
a. short-lived objects don't become old generation objects.
|
|
b. only a few oldgen objects don't have performance impact.
|
|
c. only a few references don't have performance impact.
|
|
|
|
Inserting write barriers is a very difficult hack, it is easy to
|
|
introduce critical bugs. And inserting write barriers has several areas
|
|
of overhead. Basically we don't recommend you insert write barriers.
|
|
Please carefully consider the risks.
|
|
|
|
==== Combine with built-in types
|
|
|
|
Please consider utilizing built-in types. Most built-in types support
|
|
write barrier, so you can use them to avoid manually inserting write
|
|
barriers.
|
|
|
|
For example, if your +T_DATA+ has references to other objects, then you
|
|
can move these references to Array. A +T_DATA+ object only has a reference
|
|
to an array object. Or you can also use a Struct object to gather a
|
|
+T_DATA+ object (without any references) and an Array that contains
|
|
references.
|
|
|
|
With use of such techniques, you don't need to insert write barriers
|
|
anymore.
|
|
|
|
==== Insert write barriers
|
|
|
|
\[AGAIN] Inserting write barriers is a very difficult hack, and it is
|
|
easy to introduce critical bugs. And inserting write barriers has
|
|
several areas of overhead. Basically we don't recommend you insert write
|
|
barriers. Please carefully consider the risks.
|
|
|
|
Before inserting write barriers, you need to know about RGenGC algorithm
|
|
(gc.c will help you). Macros and functions to insert write barriers are
|
|
available in include/ruby/ruby.h. An example is available in iseq.c.
|
|
|
|
For a complete guide for RGenGC and write barriers, please refer to
|
|
<https://bugs.ruby-lang.org/projects/ruby-master/wiki/RGenGC>.
|
|
|
|
== Appendix E. +RB_GC_GUARD+ to protect from premature GC
|
|
|
|
C Ruby currently uses conservative garbage collection, thus VALUE
|
|
variables must remain visible on the stack or registers to ensure any
|
|
associated data remains usable. Optimizing C compilers are not designed
|
|
with conservative garbage collection in mind, so they may optimize away
|
|
the original VALUE even if the code depends on data associated with that
|
|
VALUE.
|
|
|
|
The following example illustrates the use of +RB_GC_GUARD+ to ensure
|
|
the contents of _sptr_ remain valid while the second invocation of
|
|
+rb_str_new_cstr+ is running.
|
|
|
|
VALUE s, w;
|
|
const char *sptr;
|
|
|
|
s = rb_str_new_cstr("hello world!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
sptr = RSTRING_PTR(s);
|
|
w = rb_str_new_cstr(sptr + 6); /* Possible GC invocation */
|
|
|
|
RB_GC_GUARD(s); /* ensure s (and thus sptr) do not get GC-ed */
|
|
|
|
In the above example, +RB_GC_GUARD+ must be placed *after* the last use of
|
|
_sptr_. Placing +RB_GC_GUARD+ before dereferencing _sptr_ would be of no use.
|
|
+RB_GC_GUARD+ is only effective on the VALUE data type, not converted C
|
|
data types.
|
|
|
|
+RB_GC_GUARD+ would not be necessary at all in the above example if
|
|
non-inlined function calls are made on the _s_ VALUE after _sptr_ is
|
|
dereferenced. Thus, in the above example, calling any un-inlined
|
|
function on _s_ such as:
|
|
|
|
rb_str_modify(s);
|
|
|
|
Will ensure _s_ stays on the stack or register to prevent a
|
|
GC invocation from prematurely freeing it.
|
|
|
|
Using the +RB_GC_GUARD+ macro is preferable to using the "volatile"
|
|
keyword in C. +RB_GC_GUARD+ has the following advantages:
|
|
|
|
1. the intent of the macro use is clear
|
|
|
|
2. +RB_GC_GUARD+ only affects its call site, "volatile" generates some
|
|
extra code every time the variable is used, hurting optimization.
|
|
|
|
3. "volatile" implementations may be buggy/inconsistent in some
|
|
compilers and architectures. +RB_GC_GUARD+ is customizable for broken
|
|
systems/compilers without negatively affecting other systems.
|
|
|
|
== Appendix F. Ractor support
|
|
|
|
Ractor(s) are the parallel execution mechanism introduced in Ruby 3.0. All
|
|
ractors can run in parallel on a different OS thread (using an underlying system
|
|
provided thread), so the C extension should be thread-safe. A C extension that
|
|
can run in multiple ractors is called "Ractor-safe".
|
|
|
|
Ractor safety around C extensions has the following properties:
|
|
1. By default, all C extensions are recognized as Ractor-unsafe.
|
|
2. Ractor-unsafe C-methods may only be called from the main Ractor. If invoked
|
|
by a non-main Ractor, then a Ractor::UnsafeError is raised.
|
|
3. If an extension desires to be marked as Ractor-safe the extension should call
|
|
<tt>rb_ext_ractor_safe(true)</tt> at the +Init_+ function for the extension,
|
|
and all defined methods will be marked as Ractor-safe.
|
|
|
|
To make a "Ractor-safe" C extension, we need to check the following points:
|
|
|
|
1. Do not share unshareable objects between ractors
|
|
|
|
For example, C's global variable can lead sharing an unshareable objects
|
|
between ractors.
|
|
|
|
VALUE g_var;
|
|
VALUE set(VALUE self, VALUE v){ return g_var = v; }
|
|
VALUE get(VALUE self){ return g_var; }
|
|
|
|
<tt>set()</tt> and <tt>get()</tt> pair can share an unshareable objects
|
|
using _g_var_, and it is Ractor-unsafe.
|
|
|
|
Not only using global variables directly, some indirect data structure
|
|
such as global +st_table+ can share the objects, so please take care.
|
|
|
|
Note that class and module objects are shareable objects, so you can
|
|
keep the code <tt>cFoo = rb_define_class(...)</tt> with C's global
|
|
variables.
|
|
|
|
2. Check the thread-safety of the extension
|
|
|
|
An extension should be thread-safe. For example, the following code is
|
|
not thread-safe:
|
|
|
|
bool g_called = false;
|
|
VALUE call(VALUE self) {
|
|
if (g_called) rb_raise("recursive call is not allowed.");
|
|
g_called = true;
|
|
VALUE ret = do_something();
|
|
g_called = false;
|
|
return ret;
|
|
}
|
|
|
|
because _g_called_ global variable should be synchronized by other
|
|
ractor's threads. To avoid such data-race, some synchronization should
|
|
be used. Check include/ruby/thread_native.h and include/ruby/atomic.h.
|
|
|
|
With Ractors, all objects given as method parameters and the receiver (self)
|
|
are guaranteed to be from the current Ractor or to be shareable. As a
|
|
consequence, it is easier to make code ractor-safe than to make code generally
|
|
thread-safe. For example, we don't need to lock an array object to access the
|
|
element of it.
|
|
|
|
3. Check the thread-safety of any used library
|
|
|
|
If the extension relies on an external library, such as a function
|
|
<tt>foo()</tt> from a library libfoo, the function libfoo <tt>foo()</tt>
|
|
should be thread safe.
|
|
|
|
4. Make an object shareable
|
|
|
|
This is not required to make an extension Ractor-safe.
|
|
|
|
If an extension provides special objects defined by +rb_data_type_t+,
|
|
consider these objects can become shareable or not.
|
|
|
|
+RUBY_TYPED_FROZEN_SHAREABLE+ flag indicates that these objects can be
|
|
shareable objects if the object is frozen. This means that if the object is
|
|
frozen, the mutation of wrapped data is not allowed.
|
|
|
|
5. Others
|
|
|
|
There are possibly other points or requirements which must be considered in
|
|
the making of a Ractor-safe extension. This document will be extended as
|
|
they are discovered.
|
|
|
|
== Appendix G. Embedded TypedData
|
|
|
|
Here is an example of how to use +RUBY_TYPED_EMBEDDABLE+:
|
|
|
|
struct my_data {
|
|
struct timespec created_at;
|
|
size_t buffer_capa;
|
|
char *buffer;
|
|
};
|
|
|
|
static void
|
|
my_data_free(void *ptr)
|
|
{
|
|
struct my_data *data = (struct my_data *)ptr;
|
|
|
|
// Deliberately don't free `ptr` if it is embeddable.
|
|
// Only auxiliary memory needs to be freed.
|
|
ruby_xfree(data->buffer);
|
|
}
|
|
|
|
static size_t
|
|
my_data_size(const void *ptr)
|
|
{
|
|
const struct my_data *data = (const struct my_data *)ptr;
|
|
// We don't need to account for `sizeof(struct my_data)` because it is embedded inside the Ruby object.
|
|
// Only auxiliary memory needs to be reported.
|
|
return data->buffer_capa;
|
|
}
|
|
|
|
static const rb_data_type_t my_type = {
|
|
.wrap_struct_name = "my_type",
|
|
.function = {
|
|
.dfree = my_data_free,
|
|
.dsize = my_data_size,
|
|
},
|
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
|
|
};
|
|
|
|
static VALUE
|
|
my_data_alloc(VALUE klass)
|
|
{
|
|
struct my_data *data;
|
|
VALUE obj = TypedData_Make_Struct(klass, struct my_data, &my_type, data);
|
|
|
|
// It is fine to pass pointers into the embedded struct, for as long as
|
|
// the called function won't use it after the Ruby object has left the stack.
|
|
clock_gettime(CLOCK_REALTIME, &data->created_at);
|
|
data->buffer_capa = 1024;
|
|
data->buffer = ZALLOC_N(char, data->buffer_capa);
|
|
|
|
return obj;
|
|
}
|
|
|
|
static VALUE
|
|
my_data_read(VALUE self)
|
|
{
|
|
struct my_data *data;
|
|
TypedData_Get_Struct(self, struct my_data, &my_type, data);
|
|
|
|
// `self` is received from `rb_define_method` so `RB_GC_GUARD` isn't necessary.
|
|
return rb_str_new(data->buffer, data->buffer_capa);
|
|
}
|
|
|
|
static VALUE
|
|
my_data_m_parse(VALUE klass)
|
|
{
|
|
VALUE my_data_obj = my_data_alloc(klass);
|
|
VALUE result = my_data_read(my_data_obj);
|
|
|
|
// `my_data_obj` was allocated from C, `RB_GC_GUARD` must be used to
|
|
// ensure the compiler will keep its reference on the stack.
|
|
RB_GC_GUARD(my_data_obj);
|
|
return result;
|
|
}
|
|
|
|
void
|
|
Init_my_data(void)
|
|
{
|
|
VALUE cMyData = rb_define_class("MyData", rb_cObject);
|
|
rb_define_method(cMyData, "read", my_data_read, 0);
|
|
rb_define_singleton_method(cMyData, "parse", my_data_m_parse, 0);
|
|
}
|
|
|
|
== Appendix H. Efficent Extensions
|
|
|
|
The Ruby native extension API is large and some parts are kept for compatibility but are discouraged or "soft-deprecated".
|
|
See https://github.com/ruby/ruby/blob/master/doc/efficient_extensions.md for a list of those and tips on which APIs to use instead.
|
|
It also documents what to use for extensions to be efficient and avoid disabling Ruby VM optimizations.
|
|
|
|
--
|
|
Local variables:
|
|
fill-column: 78
|
|
end:
|
|
++
|