From: "gfim (Graham Menhennitt)" Date: 2012-11-23T05:51:21+09:00 Subject: [ruby-core:49890] [ruby-trunk - Bug #7424][Open] an embedded Ruby interpreter doesn't get the full Ruby environment unless it calls ruby_process_options() (which is not documented) Issue #7424 has been reported by gfim (Graham Menhennitt). ---------------------------------------- Bug #7424: an embedded Ruby interpreter doesn't get the full Ruby environment unless it calls ruby_process_options() (which is not documented) https://bugs.ruby-lang.org/issues/7424 Author: gfim (Graham Menhennitt) Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.3p327 (2012-11-10 revision 37606) [i686-linux] The documented way to embed a Ruby interpreter is to call: RUBY_INIT_STACK; ruby_init(); ruby_init_loadpath(); However, this leaves the Ruby environment incomplete. As an example, the following program: #include int main(int argc, char *argv[]) { RUBY_INIT_STACK; ruby_init(); ruby_init_loadpath(); rb_eval_string("p Mutex.new.methods"); return 0; } prints: [:locked?, :try_lock, :lock, :unlock, :sleep, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__] Whereas running "ruby -e 'p Mutex.new.methods'" produces: [:locked?, :try_lock, :lock, :unlock, :sleep, :synchronize, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__] Note that ":synchronize" is missing from the former. This is because ruby_init_prelude() has not been called - that's what adds synchronize() to Mutex. A workwaround is to call ruby_process_options() as in the following: #include int main(int argc, char *argv[]) { RUBY_INIT_STACK; ruby_init(); ruby_init_loadpath(); static char* args[] = { "ruby", "/dev/null" }; ruby_process_options(2, args); rb_eval_string("p Mutex.new.methods"); return 0; } This seems very clumsy! Some possible solutions are: - call ruby_init_prelude() from ruby_init() - change the linkage of ruby_init_prelude() to be non-static and have the Ruby embedded program call it explicitly (requires a documentation change). -- http://bugs.ruby-lang.org/