summaryrefslogtreecommitdiff
path: root/doc/extension.rdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/extension.rdoc')
-rw-r--r--doc/extension.rdoc542
1 files changed, 428 insertions, 114 deletions
diff --git a/doc/extension.rdoc b/doc/extension.rdoc
index 79d25e4249..9fc507706e 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -1,6 +1,8 @@
# extension.rdoc - -*- RDoc -*- created at: Mon Aug 7 16:45:54 JST 1995
-= Creating Extension Libraries for Ruby
+{日本語}[rdoc-ref:extension.ja.rdoc]
+
+= Creating extension libraries for Ruby
This document explains how to make extension libraries for Ruby.
@@ -10,8 +12,8 @@ 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.
-Data in Ruby are represented by the C type `VALUE'. Each VALUE data
-has its data type.
+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:
@@ -20,7 +22,7 @@ To retrieve C data from a VALUE, you need to:
Converting to the wrong data type may cause serious problems.
-=== Data Types
+=== Ruby data types
The Ruby interpreter has the following data types:
@@ -54,7 +56,7 @@ T_ZOMBIE :: object awaiting finalization
Most of the types are represented by C structures.
-=== Check Data Type of the VALUE
+=== Check type of the VALUE data
The macro TYPE() defined in ruby.h shows the data type of the VALUE.
TYPE() returns the constant number T_XXXX described above. To handle
@@ -88,12 +90,14 @@ There are also faster check macros for fixnums and nil.
FIXNUM_P(obj)
NIL_P(obj)
-=== Convert VALUE into C Data
+=== 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.
-Note that Qfalse is false in C also (i.e. 0), but not Qnil.
+RTEST() 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
@@ -141,7 +145,7 @@ 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
+=== Convert C data into VALUE
To convert C data to Ruby values:
@@ -167,14 +171,14 @@ INT2NUM() :: for arbitrary sized integers.
INT2NUM() converts an integer into a Bignum if it is out of the FIXNUM
range, but is a bit slower.
-=== Manipulating Ruby Data
+=== 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
+==== String functions
rb_str_new(const char *ptr, long len) ::
@@ -277,7 +281,7 @@ rb_str_modify(VALUE str) ::
you MUST call this function before modifying the contents using
RSTRING_PTR and/or rb_str_set_len.
-==== Array Functions
+==== Array functions
rb_ary_new() ::
@@ -313,11 +317,11 @@ rb_ary_aref(int argc, const VALUE *argv, VALUE ary) ::
rb_ary_entry(VALUE ary, long offset) ::
- \ary[offset]
+ ary\[offset]
rb_ary_store(VALUE ary, long offset, VALUE obj) ::
- \ary[offset] = obj
+ ary\[offset] = obj
rb_ary_subseq(VALUE ary, long beg, long len) ::
@@ -336,13 +340,13 @@ rb_ary_cat(VALUE ary, const VALUE *ptr, long len) ::
== Extending Ruby with C
-=== Adding New Features to Ruby
+=== 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
+- Methods, singleton methods
- Constants
==== Class and Module Definition
@@ -360,7 +364,7 @@ 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
+==== Method and singleton method definition
To define methods or singleton methods, use these functions:
@@ -450,15 +454,13 @@ you may rely on:
To specify whether keyword arguments are passed when calling super:
- VALUE rb_call_super(int argc, const VALUE *argv, int kw_splat)
+ 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_EMPTY_KEYWORDS :: Pass empty keywords (not included in arguments)
- (this will be removed in Ruby 3.0)
RB_PASS_CALLED_KEYWORDS :: Pass keywords if current method was called with
keywords, useful for argument delegation
@@ -467,7 +469,7 @@ available), you can use:
VALUE rb_current_receiver(void)
-==== Constant Definition
+==== Constant definition
We have 2 functions to define constants:
@@ -477,11 +479,11 @@ We have 2 functions to define constants:
The former is to define a constant under specified class/module. The
latter is to define a global constant.
-=== Use Ruby Features from C
+=== Use Ruby features from C
There are several ways to invoke Ruby's features from C code.
-==== Evaluate Ruby Programs in a String
+==== 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:
@@ -550,7 +552,7 @@ and to convert Ruby Symbol object to ID, use
ID SYM2ID(VALUE symbol)
-==== Invoke Ruby Method from C
+==== Invoke Ruby method from C
To invoke methods directly, you can use the function below
@@ -559,7 +561,7 @@ To invoke methods directly, you can use the function below
This function invokes a method on the recv, with the method name
specified by the symbol mid.
-==== Accessing the Variables and Constants
+==== Accessing the variables and constants
You can access class variables and instance variables using access
functions. Also, global variables can be shared between both
@@ -578,9 +580,9 @@ To access the constants of the class/module:
See also Constant Definition above.
-== Information Sharing Between Ruby and C
+== Information sharing between Ruby and C
-=== Ruby Constants That Can Be Accessed From C
+=== Ruby constants that can be accessed from C
As stated in section 1.3,
the following Ruby constants can be referred from C.
@@ -594,7 +596,7 @@ Qnil ::
Ruby nil in C scope.
-=== Global Variables Shared Between C and Ruby
+=== 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:
@@ -636,7 +638,7 @@ 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
+=== Encapsulate C data into a Ruby object
Sometimes you need to expose your struct in the C world as a Ruby
object.
@@ -659,30 +661,30 @@ with the next macro.
TypedData_Wrap_Struct() returns a created Ruby object as a VALUE.
-The klass argument is the class for the object.
+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.
-It is recommended that klass derives from a special class called
-Data (rb_cData) but not from Object or other ordinal classes.
-If it doesn't, you have to call rb_undef_alloc_func(klass).
-
rb_data_type_t is defined like this. Let's take a look at each
member of the struct.
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 *reserved[2];
- } function;
- const rb_data_type_t *parent;
- void *data;
- VALUE flags;
+ const char *wrap_struct_name;
+ struct {
+ void (*dmark)(void*);
+ void (*dfree)(void*);
+ size_t (*dsize)(const void *);
+ void (*dcompact)(void*);
+ void *reserved[1];
+ } function;
+ const rb_data_type_t *parent;
+ void *data;
+ VALUE flags;
};
wrap_struct_name is an identifier of this instance of the struct.
@@ -703,14 +705,22 @@ Note that it is recommended to avoid such a reference.
++
dfree is a function to free the pointer allocation.
-If this is -1, the pointer will be just freed.
+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.
-You have to fill reserved and parent with 0.
+dcompact is invoked when memory compaction took place.
+Referred Ruby objects that were marked by rb_gc_mark_movable()
+can here be updated per rb_gc_location().
+
+You have to fill reserved with 0.
+
+parent can point to another C type definition that the Ruby object
+is inherited from. Then TypedData_Get_Struct() does also accept
+derived objects.
You can fill "data" with an arbitrary value for your use.
Ruby does nothing with the member.
@@ -726,7 +736,7 @@ RUBY_TYPED_FREE_IMMEDIATELY ::
You can specify this flag if the dfree never unlocks Ruby's
internal lock (GVL).
- If this flag is not set, Ruby defers invokation of dfree()
+ If this flag is not set, Ruby defers invocation of dfree()
and invokes dfree() at the same time as finalizers.
RUBY_TYPED_WB_PROTECTED ::
@@ -739,25 +749,144 @@ RUBY_TYPED_WB_PROTECTED ::
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" in
- Appendix D.
+ 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 Ractor.make_shareable() 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.
-You can allocate and wrap the structure in one step.
+ 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+ and +RTYPEDDATA_DATA+ macro can't be used.
+ Only +RTYPEDDATA_GET_DATA+` or +TypedData_Get_Struct+ macros can be used
+ with embeddable objects.
+ Accessing `RDATA(obj)->data` or `RTYPEDDATA(obj)->data` 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+.
+
+
+Note that this macro can raise an exception. If sval to be wrapped
+holds a resource needs to be released (e.g., allocated memory, handle
+from an external library, and etc), you will have to use rb_protect.
+
+You can allocate and wrap the structure in one step, in more
+preferable manner.
TypedData_Make_Struct(klass, type, data_type, sval)
-This macro returns an allocated Data object, wrapping the pointer to
+This macro returns an allocated T_DATA object, wrapping the pointer to
the structure, which is also allocated. This macro works like:
(sval = ZALLOC(type), TypedData_Wrap_Struct(klass, data_type, sval))
+However, you should use this macro instead of "allocation then wrap"
+like the above code if it is simply allocated, because the latter can
+raise a NoMemoryError and sval will be memory leaked in that case.
+
Arguments klass and data_type work like their counterparts in
TypedData_Wrap_Struct(). A pointer to the allocated structure will
be assigned to sval, which should be a pointer of the type specified.
+==== 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 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:
+
+* <code>RUBY_TYPED_DECL_MARKING</code> =A flag that can be set on the +ruby_data_type_t+ to indicate that references are being declared as edges.
+
+* <code>RUBY_REFERENCES(ref_list_name)</code> - Define _ref_list_name_ as a list of references
+
+* <code>RUBY_REF_END</code> - The end mark of the references list.
+
+* <code>RUBY_REF_EDGE(struct, member)</code> - Declare _member_ as a VALUE edge from _struct_. Use this after +RUBY_REFERENCES_START+
+
+* +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 Data object, use the macro
+To retrieve the C pointer from the T_DATA object, use the macro
TypedData_Get_Struct().
TypedData_Get_Struct(obj, type, &data_type, sval)
@@ -772,7 +901,7 @@ 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
+=== Make the directory
% mkdir ext/dbm
@@ -799,11 +928,14 @@ 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);
@@ -813,7 +945,7 @@ Here's the example of an initializing function.
/* DBM instance method close(): no args */
rb_define_method(cDBM, "close", fdbm_close, 0);
/* DBM instance method []: 1 argument */
- rb_define_method(cDBM, "[]", fdbm_fetch, 1);
+ rb_define_method(cDBM, "[]", fdbm_aref, 1);
/* ... */
@@ -836,10 +968,19 @@ TypedData_Make_Struct.
RUBY_TYPED_FREE_IMMEDIATELY,
};
- obj = TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp);
+ 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 DBM* directly, because we want to cache size information.
+Since Object.allocate allocates an ordinary T_OBJECT type (instead
+of T_DATA), it's important to either use rb_define_alloc_func() to
+overwrite it or rb_undef_alloc_func() to delete it.
To retrieve the dbmdata structure from a Ruby object, we define the
following macro:
@@ -857,9 +998,13 @@ 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_delete(VALUE obj, VALUE keystr)
+ 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
@@ -924,6 +1069,9 @@ need to put
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
@@ -952,6 +1100,10 @@ The value of the variables below will affect the Makefile.
$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_cpflags+ 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.
@@ -960,7 +1112,7 @@ If a compilation condition is not fulfilled, you should not call
``create_makefile''. The Makefile will not be generated, compilation will
not be done.
-=== Prepare Depend (Optional)
+=== Prepare depend (Optional)
If the file named depend exists, Makefile will include that file to
check dependencies. You can make this file by invoking
@@ -999,15 +1151,32 @@ 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
+=== 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 Source Files Overview
+== 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.
-=== Ruby Language Core
+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
@@ -1016,14 +1185,14 @@ load.c :: library loading
object.c :: objects
variable.c :: variables and constants
-=== Ruby Syntax Parser
+=== Ruby syntax parser
parse.y :: grammar definition
parse.c :: automatically generated from parse.y
defs/keywords :: reserved keywords
lex.c :: automatically generated from keywords
-=== Ruby Evaluator (a.k.a. YARV)
+=== Ruby evaluator (a.k.a. YARV)
compile.c
eval.c
@@ -1049,9 +1218,8 @@ lex.c :: automatically generated from keywords
-> opt*.inc : automatically generated
-> vm.inc : automatically generated
-=== Regular Expression Engine (Oniguruma)
+=== Regular expression engine (Onigumo)
- regex.c
regcomp.c
regenc.c
regerror.c
@@ -1059,7 +1227,7 @@ lex.c :: automatically generated from keywords
regparse.c
regsyntax.c
-=== Utility Functions
+=== Utility functions
debug.c :: debug symbols for C debugger
dln.c :: dynamic loading
@@ -1067,7 +1235,7 @@ st.c :: general purpose hash table
strftime.c :: formatting times
util.c :: misc utilities
-=== Ruby Interpreter Implementation
+=== Ruby interpreter implementation
dmyext.c
dmydln.c
@@ -1081,7 +1249,7 @@ util.c :: misc utilities
gem_prelude.rb
prelude.rb
-=== Class Library
+=== Class library
array.c :: Array
bignum.c :: Bignum
@@ -1120,13 +1288,13 @@ transcode.c :: Encoding::Converter
enc/*.c :: encoding classes
enc/trans/* :: codepoint mapping tables
-=== goruby Interpreter Implementation
+=== goruby interpreter implementation
goruby.c
golf_prelude.rb : goruby specific libraries.
-> golf_prelude.c : automatically generated
-== Appendix B. Ruby Extension API Reference
+== Appendix B. Ruby extension API reference
=== Types
@@ -1136,7 +1304,7 @@ VALUE ::
such as struct RString, etc. To refer the values in structures, use
casting macros like RSTRING(obj).
-=== Variables and Constants
+=== Variables and constants
Qnil ::
@@ -1150,7 +1318,7 @@ Qfalse ::
false object
-=== C Pointer Wrapping
+=== C pointer wrapping
Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval) ::
@@ -1170,7 +1338,7 @@ Data_Get_Struct(data, type, sval) ::
This macro retrieves the pointer value from DATA, and assigns it to
the variable sval.
-=== Checking Data Types
+=== Checking VALUE types
RB_TYPE_P(value, type) ::
@@ -1200,7 +1368,7 @@ void Check_Type(VALUE value, int type) ::
Ensures +value+ is of the given internal +type+ or raises a TypeError
-=== Data Type Conversion
+=== VALUE type conversion
FIX2INT(value), INT2FIX(i) ::
@@ -1284,7 +1452,7 @@ rb_str_new2(s) ::
char * -> String
-=== Defining Classes and Modules
+=== Defining classes and modules
VALUE rb_define_class(const char *name, VALUE super) ::
@@ -1311,7 +1479,7 @@ void rb_extend_object(VALUE object, VALUE module) ::
Extend the object with the module's attributes.
-=== Defining Global Variables
+=== Defining global variables
void rb_define_variable(const char *name, VALUE *var) ::
@@ -1355,7 +1523,7 @@ void rb_gc_register_mark_object(VALUE object) ::
Tells GC to protect the +object+, which may not be referenced anywhere.
-=== Constant Definition
+=== Constant definition
void rb_define_const(VALUE klass, const char *name, VALUE val) ::
@@ -1367,7 +1535,7 @@ void rb_define_global_const(const char *name, VALUE val) ::
rb_define_const(rb_cObject, name, val)
-=== Method Definition
+=== Method definition
rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) ::
@@ -1423,28 +1591,6 @@ rb_scan_args(int argc, VALUE *argv, const char *fmt, ...) ::
; argument captured as a hash.
; If keyword arguments are not
; provided, returns nil.
- ;
- ; Currently, will also consider
- ; final argument as keywords if
- ; it is a hash or can be
- ; converted to a hash with
- ; #to_hash. When the last
- ; argument is nil, it is
- ; captured if it is not
- ; ambiguous to take it as
- ; empty option hash; i.e. '*'
- ; is not specified and
- ; arguments are given more
- ; than sufficient.
- ;
- ; However, handling final
- ; argument as keywords if
- ; method was not called with
- ; keywords (whether final
- ; argument is hash or nil) is
- ; deprecated. In that case, a
- ; warning will be emitted, and
- ; in Ruby 3.0 it will be an error.
sym-for-block-arg := "&" ; Indicates that an iterator
; block should be captured if
; given
@@ -1469,8 +1615,6 @@ rb_scan_args_kw(int kw_splat, int argc, VALUE *argv, const char *fmt, ...) ::
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_EMPTY_KEYWORDS :: Don't treat a final hash as keywords.
- (this will be removed in Ruby 3.0)
RB_SCAN_ARGS_LAST_HASH_KEYWORDS :: Treat a final argument as keywords if it
is a hash, and not as keywords otherwise.
@@ -1567,7 +1711,7 @@ int rb_respond_to(VALUE obj, ID id) ::
Returns true if the object responds to the message specified by id.
-=== Instance Variables
+=== Instance variables
VALUE rb_iv_get(VALUE obj, const char *name) ::
@@ -1578,7 +1722,7 @@ VALUE rb_iv_set(VALUE obj, const char *name, VALUE val) ::
Sets the value of the instance variable.
-=== Control Structure
+=== Control structure
VALUE rb_block_call(VALUE recv, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2) ::
@@ -1674,7 +1818,7 @@ void rb_iter_break_value(VALUE value) ::
return the given argument value. This function never return to the
caller.
-=== Exceptions and Errors
+=== Exceptions and errors
void rb_warn(const char *fmt, ...) ::
@@ -1747,7 +1891,7 @@ int rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) ::
Use a NULL +timeout+ to wait indefinitely.
-=== I/O Multiplexing
+=== I/O multiplexing
Ruby supports I/O multiplexing based on the select(2) system call.
The Linux select_tut(2) manpage
@@ -1799,7 +1943,7 @@ int rb_thread_fd_select(int nfds, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_
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
+=== Initialize and start the interpreter
The embedding API functions are below (not needed for extension libraries):
@@ -1824,7 +1968,7 @@ void ruby_script(char *name) ::
Specifies the name of the script ($0).
-=== Hooks for the Interpreter Events
+=== Hooks for the interpreter events
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data) ::
@@ -1866,7 +2010,7 @@ void rb_gc_adjust_memory_usage(ssize_t diff) ::
is decreased; a memory block is freed or a block is reallocated as
smaller size. This function may trigger the GC.
-=== Macros for Compatibility
+=== Macros for compatibility
Some macros to check API compatibilities are available by default.
@@ -1877,13 +2021,13 @@ NORETURN_STYLE_NEW ::
HAVE_RB_DEFINE_ALLOC_FUNC ::
Means that function rb_define_alloc_func() is provided, that means the
- allocation framework is used. This is same as the result of
+ allocation framework is used. This is the same as the result of
have_func("rb_define_alloc_func", "ruby.h").
HAVE_RB_REG_NEW_STR ::
Means that function rb_reg_new_str() is provided, that creates Regexp
- object from String object. This is same as the result of
+ object from String object. This is the same as the result of
have_func("rb_reg_new_str", "ruby.h").
HAVE_RB_IO_T ::
@@ -1901,6 +2045,9 @@ HAVE_RUBY_*_H ::
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 rb_add_event_hook() takes the third argument `data', to be
@@ -1946,6 +2093,7 @@ the <code>*_kw</code> functions introduced in Ruby 2.7.
#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
@@ -2049,7 +2197,7 @@ Before inserting write barriers, you need to know about RGenGC algorithm
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-trunk/wiki/RGenGC>.
+<https://bugs.ruby-lang.org/projects/ruby-master/wiki/RGenGC>.
== Appendix E. RB_GC_GUARD to protect from premature GC
@@ -2100,6 +2248,172 @@ keyword in C. RB_GC_GUARD has the following advantages:
compilers and architectures. RB_GC_GUARD is customizable for broken
systems/compilers without negatively affecting other systems.
-:enddoc: Local variables:
-:enddoc: fill-column: 70
-:enddoc: end:
+== 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 rb_ext_ractor_safe(true) 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; }
+
+ set() and get() 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 "cFoo = rb_define_class(...)" 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 foo() from
+ a library libfoo, the function libfoo foo() 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 need 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_struct)` because it is embedded inside the Ruby object.
+ // Only auxiliary memory need 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);
+
+ // Is it fine to pass pointers into the embedded struct, for as long as
+ // the called function won't use it after the Ruby object have 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_m_parse(VALUE klass)
+ {
+ struct my_data *data;
+ VALUE my_data_obj = my_data_alloc(klass);
+ TypedData_Get_Struct(obj, struct my_data, &my_type, data);
+
+ // `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)
+ }
+
+ static VALUE
+ my_data_read(VALUE self)
+ {
+ struct my_data *data;
+ TypedData_Get_Struct(obj, 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)
+ }
+
+ void
+ Init_my_data(void)
+ {
+ VALUE cMyData = rb_define_class("MyData");
+ rb_define_method(cMyData, "read", my_data_read, 0);
+ rb_define_singleton_method(cMyData, "parse", my_data_m_parse, 0);
+ }
+
+--
+Local variables:
+fill-column: 70
+end:
+++