Note that there are some explanatory texts on larger screens.

plurals
  1. POCalling Ruby function from C++ in a loop results in "stack level too deep"
    primarykey
    data
    text
    <p>I'm trying to run blocks of Ruby code from C++. I have two Ruby functions, one called Init(), and one called Loop(). The problem I have is that I can only Loop() so many times before I get a "stack level too deep" from SystemStackError. My Ruby code is not recursive as far as I can tell. As you can see, so far this Ruby code is just for a proof-of-concept and loaded with nothing but debug-style stuff and blinking a light on a panel. Here's the Ruby code:</p> <pre><code>def Init() puts 'Hello from script\'s Init()!' $i = 0 $p = Panel.new $p.Debug $p.Extinguish( "Running" ) $p.Illuminate( "Fault" ) end def Loop() puts 'Hello from Loop!' + $i.to_s $i += 1 puts $p $p.Debug $p.Illuminate( "Running" ) if $i % 2 == 1 $p.Extinguish( "Running" ) if $i % 2 != 1 end </code></pre> <p>My implementation of Panel in C++ is:</p> <pre><code>ruby_init(); VALUE cPanel; cPanel = rb_define_class( "Panel", rb_cObject ); rb_define_singleton_method( cPanel, "new", (RubyMethod*)&amp;StaticRubyNew, 0 ); rb_define_method( cPanel, "Debug", (RubyMethod*)&amp;StaticRubyDebug, 0 ); rb_define_method( cPanel, "Extinguish", (RubyMethod*)&amp;StaticRubyExtinguish, 1 ); rb_define_method( cPanel, "Illuminate", (RubyMethod*)&amp;StaticRubyIlluminate, 1 ); </code></pre> <p>I call the script functions as follows:</p> <pre><code>rb_eval_string( program ); rb_funcall( Qnil, rb_intern( "Init" ), 0, NULL ); // In a 200ms loop: rb_funcall( Qnil, rb_intern( "Loop" ), 0, NULL ); </code></pre> <p>Nothing worked until I wrote a (suspect) implementation of <strong>new</strong>:</p> <pre><code>VALUE MainWidget::RubyNew( VALUE clas ) { // Looks like we have to return *something* instead of Qnil, even if I // don't have anything to wrap yet. const char* s = "Dude"; VALUE tdata = Data_Wrap_Struct( clas, StaticRubyMark, StaticRubyFree, const_cast&lt;char*&gt;(s) ); return tdata; } </code></pre> <p>RubyMark and RubyFree don't do anything, and RubyDebug, RubyIlluminate, etc. don't do anything remarkable either for the problem at hand.</p> <p>I've tried wrapping Init and Loop in a class as class methods, so I can call rb_funcall() with a real receiver. I've tried getting a backtrace by calling through rb_protect() (the backtrace appears empty). Nothing online seems to have the secret for loading the script as a string, so rb_eval_string() is a guess. rb_load_file() doesn't work either.</p> <p>Why does this cause stack problems? I can edit my Ruby script, adding or removing code, and the stack blows after executing various numbers of loops. The number of loops that I can execute has no discernible relationship to the number of lines. If I remove a line, I might get 45 loops. If I remove another, I might get over 2000. What am I doing wrong?</p> <p>A little more code in light of the response below--this is to give C++ methods to Ruby API calls (which expect C-style functions):</p> <pre><code>typedef VALUE (RubyMethod)(...); extern "C" /*static*/ VALUE StaticRubyNew( VALUE self ) { return MainWidget::M_this-&gt;RubyNew( self ); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload