For several years I've been using the Ruby C API to add the ability to use Ruby code in my C text editor (a variant of MicroEMACS). This has been working well in Linux Mint 21 (essentially the same as Ubuntu 22.04), which uses Ruby 3.0.
Then I started running this code on Mint 22 (Ubuntu 24.04), which uses Ruby 3.2, and things failed. Specifically, certain commonly used Class methods started giving unexpected output or exceptions about missing methods. The problems I ran into (there may be others I don't know about) were that Symbol#to_s seems to do nothing, and Time.now is undefined. Then when I tried this same code on Fedora 42, which uses Ruby 3.4, Array#last was now undefined, in addition to the other problems.
These problems don't occur when I run Ruby as a separate process.
I have boiled down the problems into a simple test program:
#include <ruby.h> #include <string.h> void check_exception (int state) { if (state) { printf("Exception occurred!\n"); VALUE exception = rb_errinfo (); if (RTEST(exception)) { VALUE msg; VALUE msglines; VALUE bt; msg = rb_funcall (exception, rb_intern("to_s"), 0); printf("%s\n", StringValueCStr (msg)); } /* rb_set_errinfo (Qnil); */ /* This causes a coredump for some reason. */ } } void run (const char *rubycode) { int state; printf("====\nAbout to run '%s'\n", rubycode); rb_eval_string_protect(rubycode, &state); check_exception (state); } int main(int argc, char* argv[]) { ruby_init(); ruby_init_loadpath(); run ("puts \"Hello, world!\""); /* This should print "sym" but prints #<Symbol:0x000000000076010c> instead. * The missing Symbol#to_s causes all the subsequent error messages * to print #<Symbol:0x....> instead of the actual method name. */ run ("puts :sym.to_s"); /* Array#last is undefined. */ run ("puts [0].last"); /* Time.now is undefined. */ run ("puts Time.now"); return ruby_cleanup(0); } Here is the output on Fedora 42:
==== About to run 'puts "Hello, world!"' Hello, world! ==== About to run 'puts :sym.to_s' #<Symbol:0x000000000076010c> ==== About to run 'puts [0].last' Exception occurred! undefined method '#<Symbol:0x000000000040610c>' for an instance of Array ==== About to run 'puts Time.now' Exception occurred! undefined method '#<Symbol:0x000000000076110c>' for class Time eval:1:in '<main>': undefined method '#<Symbol:0x000000000076110c>' for class Time (NoMethodError) eval:1:in '<main>': undefined method '#<Symbol:0x000000000040610c>' for an instance of Array (NoMethodError) Clearly, the Ruby interpreter is doing something to define these methods, but I don't know how to get them to be defined using the C API. Are there some additional API calls that I'm missing in this little test program?