3#include "eval_intern.h"
5#include "internal/class.h"
6#include "internal/eval.h"
7#include "internal/error.h"
8#include "internal/file.h"
9#include "internal/gc.h"
10#include "internal/hash.h"
11#include "internal/load.h"
12#include "internal/namespace.h"
13#include "internal/st.h"
14#include "internal/variable.h"
23VALUE rb_cNamespaceEntry = 0;
24VALUE rb_mNamespaceLoader = 0;
37static bool tmp_dir_has_dirsep;
39#define NAMESPACE_TMP_PREFIX "_ruby_ns_"
42# define MAXPATHLEN 1024
51bool ruby_namespace_enabled =
false;
52bool ruby_namespace_init_done =
false;
58rb_namespace_init_done(
void)
60 ruby_namespace_init_done =
true;
64rb_root_namespace(
void)
66 return root_namespace;
70rb_main_namespace(
void)
72 return main_namespace;
76rb_current_namespace(
void)
86 return root_namespace;
88 return rb_vm_current_namespace(GET_EC());
92rb_loading_namespace(
void)
95 return root_namespace;
97 return rb_vm_loading_namespace(GET_EC());
100static long namespace_id_counter = 0;
103namespace_generate_id(
void)
107 id = ++namespace_id_counter;
126 ns->expanded_load_path =
rb_ary_dup(root->expanded_load_path);
128 ns->load_path_check_cache = 0;
129 ns->loaded_features =
rb_ary_dup(root->loaded_features);
131 ns->loaded_features_index = st_init_numtable();
132 ns->loaded_features_realpaths = rb_hash_dup(root->loaded_features_realpaths);
133 ns->loaded_features_realpath_map = rb_hash_dup(root->loaded_features_realpath_map);
134 ns->loading_table = st_init_strtable();
135 ns->ruby_dln_libmap = rb_hash_new_with_size(0);
136 ns->gvar_tbl = rb_hash_new_with_size(0);
139 ns->is_optional =
true;
143rb_namespace_gc_update_references(
void *ptr)
149 ns->ns_object = rb_gc_location(ns->ns_object);
151 ns->top_self = rb_gc_location(ns->top_self);
152 ns->load_path = rb_gc_location(ns->load_path);
153 ns->expanded_load_path = rb_gc_location(ns->expanded_load_path);
154 ns->load_path_snapshot = rb_gc_location(ns->load_path_snapshot);
155 if (ns->load_path_check_cache) {
156 ns->load_path_check_cache = rb_gc_location(ns->load_path_check_cache);
158 ns->loaded_features = rb_gc_location(ns->loaded_features);
159 ns->loaded_features_snapshot = rb_gc_location(ns->loaded_features_snapshot);
160 ns->loaded_features_realpaths = rb_gc_location(ns->loaded_features_realpaths);
161 ns->loaded_features_realpath_map = rb_gc_location(ns->loaded_features_realpath_map);
162 ns->ruby_dln_libmap = rb_gc_location(ns->ruby_dln_libmap);
163 ns->gvar_tbl = rb_gc_location(ns->gvar_tbl);
167rb_namespace_entry_mark(
void *ptr)
172 rb_gc_mark(ns->ns_object);
173 rb_gc_mark(ns->top_self);
174 rb_gc_mark(ns->load_path);
175 rb_gc_mark(ns->expanded_load_path);
176 rb_gc_mark(ns->load_path_snapshot);
177 rb_gc_mark(ns->load_path_check_cache);
178 rb_gc_mark(ns->loaded_features);
179 rb_gc_mark(ns->loaded_features_snapshot);
180 rb_gc_mark(ns->loaded_features_realpaths);
181 rb_gc_mark(ns->loaded_features_realpath_map);
182 if (ns->loading_table) {
183 rb_mark_tbl(ns->loading_table);
185 rb_gc_mark(ns->ruby_dln_libmap);
186 rb_gc_mark(ns->gvar_tbl);
190free_loading_table_entry(st_data_t key, st_data_t value, st_data_t arg)
197namespace_entry_free(
void *ptr)
200 if (ns->loading_table) {
201 st_foreach(ns->loading_table, free_loading_table_entry, 0);
202 st_free_table(ns->loading_table);
203 ns->loading_table = 0;
208namespace_entry_memsize(
const void *ptr)
212 rb_st_memsize(ns->loaded_features_index) + \
213 rb_st_memsize(ns->loading_table);
219 rb_namespace_entry_mark,
220 namespace_entry_free,
221 namespace_entry_memsize,
222 rb_namespace_gc_update_references,
224 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
228rb_namespace_entry_alloc(
VALUE klass)
232 namespace_entry_initialize(entry);
237get_namespace_struct_internal(
VALUE entry)
245rb_get_namespace_t(
VALUE namespace)
248 ID id_namespace_entry;
250 VM_ASSERT(
namespace);
252 if (
NIL_P(
namespace))
253 return root_namespace;
255 VM_ASSERT(NAMESPACE_OBJ_P(
namespace));
257 CONST_ID(id_namespace_entry,
"__namespace_entry__");
258 entry = rb_attr_get(
namespace, id_namespace_entry);
259 return get_namespace_struct_internal(entry);
265 VM_ASSERT(ns && ns->ns_object);
266 return ns->ns_object;
276namespace_initialize(
VALUE namespace)
281 ID id_namespace_entry;
282 CONST_ID(id_namespace_entry,
"__namespace_entry__");
284 if (!rb_namespace_available()) {
285 rb_raise(
rb_eRuntimeError,
"Namespace is disabled. Set RUBY_NAMESPACE=1 environment variable to use Namespace.");
289 ns = get_namespace_struct_internal(entry);
291 ns->ns_object =
namespace;
292 ns->ns_id = namespace_generate_id();
298 RCLASS_SET_PRIME_CLASSEXT_WRITABLE(
namespace,
true);
302 object_classext = RCLASS_EXT_WRITABLE_IN_NS(rb_cObject, ns);
303 RCLASS_SET_CONST_TBL(
namespace, RCLASSEXT_CONST_TBL(object_classext),
true);
317rb_namespace_s_getenabled(
VALUE recv)
319 return RBOOL(rb_namespace_available());
331rb_namespace_s_current(
VALUE recv)
335 if (!rb_namespace_available())
338 ns = rb_vm_current_namespace(GET_EC());
339 VM_ASSERT(ns && ns->ns_object);
340 return ns->ns_object;
350rb_namespace_s_is_builtin_p(
VALUE recv,
VALUE klass)
352 if (RCLASS_PRIME_CLASSEXT_READABLE_P(klass) && !RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass))
364rb_namespace_load_path(
VALUE namespace)
366 VM_ASSERT(NAMESPACE_OBJ_P(
namespace));
367 return rb_get_namespace_t(
namespace)->load_path;
371UINT rb_w32_system_tmpdir(WCHAR *path, UINT
len);
376system_default_tmpdir(
void)
380 WCHAR tmppath[_MAX_PATH];
381 UINT
len = rb_w32_system_tmpdir(tmppath, numberof(tmppath));
383 int blen = WideCharToMultiByte(CP_UTF8, 0, tmppath,
len, NULL, 0, NULL, NULL);
384 char *tmpdir =
xmalloc(blen + 1);
385 WideCharToMultiByte(CP_UTF8, 0, tmppath,
len, tmpdir, blen, NULL, NULL);
389#elif defined _CS_DARWIN_USER_TEMP_DIR
390 char path[MAXPATHLEN];
391 size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, path,
sizeof(path));
394 if (
len >
sizeof(path)) {
395 confstr(_CS_DARWIN_USER_TEMP_DIR, tmpdir,
len);
398 memcpy(tmpdir, path,
len);
407check_tmpdir(
const char *dir)
411 if (!dir)
return FALSE;
412 if (stat(dir, &st))
return FALSE;
414# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
416 if (!S_ISDIR(st.st_mode))
return FALSE;
421 if (st.st_mode & S_IWOTH) {
423 if (!(st.st_mode & S_ISVTX))
return FALSE;
428 if (access(dir, W_OK))
return FALSE;
437# define RETURN_ENV(name) \
438 if (check_tmpdir(tmpdir = getenv(name))) return ruby_strdup(tmpdir)
439 RETURN_ENV(
"TMPDIR");
441 tmpdir = system_default_tmpdir();
442 if (check_tmpdir(tmpdir))
return tmpdir;
450sprint_ext_filename(
char *str,
size_t size,
long namespace_id,
const char *prefix,
const char *basename)
452 if (tmp_dir_has_dirsep) {
453 return snprintf(str, size,
"%s%sp%"PRI_PIDT_PREFIX"u_%ld_%s", tmp_dir, prefix, getpid(), namespace_id, basename);
455 return snprintf(str, size,
"%s%s%sp%"PRI_PIDT_PREFIX"u_%ld_%s", tmp_dir, DIRSEP, prefix, getpid(), namespace_id, basename);
460copy_ext_file_error(
char *message,
size_t size)
462 int error = GetLastError();
464 size_t len = snprintf(message, size,
"%d: ", error);
466#define format_message(sublang) FormatMessage(\
467 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
468 NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
469 message + len, size - len, NULL)
470 if (format_message(SUBLANG_ENGLISH_US) == 0)
471 format_message(SUBLANG_DEFAULT);
472 for (p = message +
len; *p; p++) {
473 if (*p ==
'\n' || *p ==
'\r')
480copy_ext_file_error(
char *message,
size_t size,
int copy_retvalue,
char *src_path,
char *dst_path)
482 switch (copy_retvalue) {
484 snprintf(message, size,
"can't open the extension path: %s", src_path);
486 snprintf(message, size,
"can't open the file to write: %s", dst_path);
488 snprintf(message, size,
"failed to read the extension path: %s", src_path);
490 snprintf(message, size,
"failed to write the extension path: %s", dst_path);
492 rb_bug(
"unknown return value of copy_ext_file: %d", copy_retvalue);
499copy_ext_file(
char *src_path,
char *dst_path)
504 WCHAR *w_src = rb_w32_mbstr_to_wstr(CP_UTF8, src_path, -1, NULL);
505 WCHAR *w_dst = rb_w32_mbstr_to_wstr(CP_UTF8, dst_path, -1, NULL);
506 if (!w_src || !w_dst) {
510 rvalue = CopyFileW(w_src, w_dst, FALSE) ? 0 : 1;
517 size_t read = 0, wrote, written = 0;
518 size_t maxread =
sizeof(buffer);
523 src = fopen(src_path,
"rb");
527 dst = fopen(dst_path,
"wb");
533 read = fread(buffer, 1,
sizeof(buffer), src);
537 wrote = fwrite(buffer+written, 1, read-written, dst);
538 if (wrote < read-written) {
552 if (read < maxread) {
553 if (clean_read && feof(src)) {
557 else if (ferror(src)) {
570#if defined __CYGWIN__ || defined DOSISH
571#define isdirsep(x) ((x) == '/' || (x) == '\\')
573#define isdirsep(x) ((x) == '/')
576#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
577#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
580fname_without_suffix(
const char *fname,
char *rvalue,
size_t rsize)
582 size_t len = strlen(fname);
584 for (pos = fname +
len; pos > fname; pos--) {
585 if (IS_SOEXT(pos) || IS_DLEXT(pos)) {
589 if (fname +
len - pos > DLEXT_MAXLEN)
break;
591 if (
len > rsize - 1)
len = rsize - 1;
592 memcpy(rvalue, fname,
len);
597escaped_basename(
const char *path,
const char *fname,
char *rvalue,
size_t rsize)
600 const char *leaf = path, *found;
602 while ((found = strstr(leaf + 1, fname)) != NULL) {
605 strlcpy(rvalue, leaf, rsize);
606 for (pos = rvalue; *pos; pos++) {
607 if (isdirsep(*pos)) {
616 char ext_path[MAXPATHLEN], fname2[MAXPATHLEN], basename[MAXPATHLEN];
617 int copy_error, wrote;
618 char *src_path = RSTRING_PTR(path), *fname_ptr = RSTRING_PTR(fname);
621 fname_without_suffix(fname_ptr, fname2,
sizeof(fname2));
622 escaped_basename(src_path, fname2, basename,
sizeof(basename));
624 wrote = sprint_ext_filename(ext_path,
sizeof(ext_path), ns->ns_id, NAMESPACE_TMP_PREFIX, basename);
625 if (wrote >= (
int)
sizeof(ext_path)) {
626 rb_bug(
"Extension file path in namespace was too long");
628 copy_error = copy_ext_file(src_path, ext_path);
632 copy_ext_file_error(message,
sizeof(message));
634 copy_ext_file_error(message,
sizeof(message), copy_error, src_path, ext_path);
636 rb_raise(
rb_eLoadError,
"can't prepare the extension file for namespaces (%s from %s): %s", ext_path, src_path, message);
647rb_namespace_load(
int argc,
VALUE *argv,
VALUE namespace)
652 rb_vm_frame_flag_set_ns_require(GET_EC());
654 VALUE args = rb_ary_new_from_args(2, fname, wrap);
655 return rb_load_entrypoint(args);
659rb_namespace_require(
VALUE namespace,
VALUE fname)
661 rb_vm_frame_flag_set_ns_require(GET_EC());
667rb_namespace_require_relative(
VALUE namespace,
VALUE fname)
669 rb_vm_frame_flag_set_ns_require(GET_EC());
671 return rb_require_relative_entrypoint(fname);
675initialize_root_namespace(
void)
677 VALUE root_namespace, entry;
678 ID id_namespace_entry;
685 root->load_path_check_cache = 0;
690 root->loaded_features_index = st_init_numtable();
691 root->loaded_features_realpaths = rb_hash_new();
693 root->loaded_features_realpath_map = rb_hash_new();
696 root->ruby_dln_libmap = rb_hash_new_with_size(0);
697 root->gvar_tbl = rb_hash_new_with_size(0);
699 vm->root_namespace = root;
701 if (rb_namespace_available()) {
702 CONST_ID(id_namespace_entry,
"__namespace_entry__");
705 RCLASS_SET_PRIME_CLASSEXT_WRITABLE(root_namespace,
true);
706 RCLASS_SET_CONST_TBL(root_namespace, RCLASSEXT_CONST_TBL(RCLASS_EXT_PRIME(rb_cObject)),
true);
708 root->ns_id = namespace_generate_id();
709 root->ns_object = root_namespace;
712 rb_ivar_set(root_namespace, id_namespace_entry, entry);
716 root->ns_object =
Qnil;
733 return rb_iseq_eval(iseq, ns);
736static int namespace_experimental_warned = 0;
739rb_initialize_main_namespace(
void)
745 VM_ASSERT(rb_namespace_available());
747 if (!namespace_experimental_warned) {
749 "Namespace is experimental, and the behavior may change in the future!\n"
750 "See doc/namespace.md for known issues, etc.");
751 namespace_experimental_warned = 1;
755 VM_ASSERT(NAMESPACE_OBJ_P(main_ns));
756 ns = rb_get_namespace_t(main_ns);
757 ns->ns_object = main_ns;
758 ns->ns_id = namespace_generate_id();
760 ns->is_optional =
false;
764 vm->main_namespace = main_namespace = ns;
768rb_namespace_inspect(
VALUE obj)
776 ns = rb_get_namespace_t(obj);
779 if (NAMESPACE_ROOT_P(ns)) {
782 if (NAMESPACE_USER_P(ns)) {
785 if (NAMESPACE_MAIN_P(ns)) {
788 else if (NAMESPACE_OPTIONAL_P(ns)) {
796rb_namespace_loading_func(
int argc,
VALUE *argv,
VALUE _self)
798 rb_vm_frame_flag_set_ns_require(GET_EC());
803namespace_define_loader_method(
const char *name)
810Init_root_namespace(
void)
812 root_namespace->loading_table = st_init_strtable();
816Init_enable_namespace(
void)
818 const char *env = getenv(
"RUBY_NAMESPACE");
819 if (env && strlen(env) == 1 && env[0] ==
'1') {
820 ruby_namespace_enabled =
true;
823 ruby_namespace_init_done =
true;
831rb_namespace_s_root(
VALUE recv)
833 return root_namespace->ns_object;
838rb_namespace_s_main(
VALUE recv)
840 return main_namespace->ns_object;
844classname(
VALUE klass)
846 VALUE p = RCLASS_CLASSPATH(klass);
848 return RSTRING_PTR(p);
851 return "NonClassValue";
854static enum rb_id_table_iterator_result
855dump_classext_methods_i(
ID mid,
VALUE _val,
void *data)
859 return ID_TABLE_CONTINUE;
862static enum rb_id_table_iterator_result
863dump_classext_constants_i(
ID mid,
VALUE _val,
void *data)
867 return ID_TABLE_CONTINUE;
877 snprintf(buf, 4096,
"Namespace %ld:%s classext %p\n",
878 RCLASSEXT_NS(ext)->ns_id, is_prime ?
" prime" :
"", (void *)ext);
881 snprintf(buf, 2048,
" Super: %s\n", classname(RCLASSEXT_SUPER(ext)));
884 tbl = RCLASSEXT_M_TBL(ext);
887 rb_id_table_foreach(RCLASSEXT_M_TBL(ext), dump_classext_methods_i, (
void *)ary);
889 snprintf(buf, 4096,
" Methods(%ld): ",
RARRAY_LEN(ary));
898 tbl = RCLASSEXT_CONST_TBL(ext);
901 rb_id_table_foreach(tbl, dump_classext_constants_i, (
void *)ary);
903 snprintf(buf, 4096,
" Constants(%ld): ",
RARRAY_LEN(ary));
938 snprintf(buf, 2048,
"Non-class/module value: %p (%s)\n", (
void *)klass, rb_type_str(
BUILTIN_TYPE(klass)));
943 snprintf(buf, 2048,
"Class: %p (%s)%s\n",
944 (
void *)klass, classname(klass), RCLASS_SINGLETON_P(klass) ?
" [singleton]" :
"");
947 snprintf(buf, 2048,
"Module: %p (%s)\n", (
void *)klass, classname(klass));
951 ext = RCLASS_EXT_PRIME(klass);
952 ns = RCLASSEXT_NS(ext);
953 snprintf(buf, 2048,
"Prime classext namespace(%ld,%s), readable(%s), writable(%s)\n",
955 NAMESPACE_ROOT_P(ns) ?
"root" : (NAMESPACE_MAIN_P(ns) ?
"main" :
"optional"),
956 RCLASS_PRIME_CLASSEXT_READABLE_P(klass) ?
"t" :
"f",
957 RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass) ?
"t" :
"f");
960 classext_tbl = RCLASS_CLASSEXT_TBL(klass);
965 snprintf(buf, 2048,
"Non-prime classexts: %zu\n", st_table_size(classext_tbl));
969 rb_class_classext_foreach(klass, dump_classext_i, (
void *)res);
986 tmp_dir = system_tmpdir();
987 tmp_dir_has_dirsep = (strcmp(tmp_dir + (strlen(tmp_dir) - strlen(DIRSEP)), DIRSEP) == 0);
996 initialize_root_namespace();
1000 namespace_define_loader_method(
"require");
1001 namespace_define_loader_method(
"require_relative");
1002 namespace_define_loader_method(
"load");
1004 if (rb_namespace_available()) {
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
Ruby-level global variables / constants, visible from C.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
#define xfree
Old name of ruby_xfree.
#define xmalloc
Old name of ruby_xmalloc.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define Qtrue
Old name of RUBY_Qtrue.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define NIL_P
Old name of RB_NIL_P.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define CONST_ID
Old name of RUBY_CONST_ID.
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_eLoadError
LoadError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
@ RB_WARN_CATEGORY_EXPERIMENTAL
Warning is for experimental features.
VALUE rb_cNamespace
Namespace class.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass)
Identical to rb_class_new_instance(), except it passes the passed keywords if any to the #initialize ...
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_cModule
Module class.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
VALUE rb_ary_join(VALUE ary, VALUE sep)
Recursively stringises the elements of the passed array, flattens that result, then joins the sequenc...
VALUE rb_require_string(VALUE feature)
Finds and loads the given feature, if absent.
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
void rb_const_set(VALUE space, ID name, VALUE val)
Names a constant.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
int len
Length of the buffer.
char * ruby_strdup(const char *str)
This is our own version of strdup(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
#define PRI_PIDT_PREFIX
A rb_sprintf() format prefix to be used for a pid_t parameter.
#define RARRAY_LEN
Just another name of rb_array_len.
#define StringValue(v)
Ensures that the parameter object is a String.
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
#define RTEST
This is an old name of RB_TEST.
This is the struct that holds necessary info for a struct.
Internal header for Namespace.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.