<br><div class="gmail_quote">2008/4/8 Aaron J. Seigo &lt;<a href="mailto:aseigo@kde.org">aseigo@kde.org</a>&gt;:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">On Monday 07 April 2008, Richard Dale wrote:<br>
&gt; I&#39;ve just commited a fix based on the SWIG macros and it all works very<br>
&gt; well now - phew!<br>
<br>
</div>wow..that&#39;s a bit crazy.<br>
<br>
does this impact both the kross ScriptEngine as well as your &quot;no, it&#39;s really<br>
a c++ plugin ;)&quot; code? or just one or the other?</blockquote><div>&nbsp;Yes I think it will affect kross because the state of the stack when kross is loaded might be different from when the plasma runtime make callbacks to it. In the case of he QtRuby based applet the stack base when loading was above the stackbase when running (ie there were more C++ calls involved in loading the applet, than there were when running it). <br>
<br>Currently it is possible that there are less C++ stack activations involved in loading kross than there are when invoking callbacks, and it might be ok. But maybe one day you add some extra nested C++ calls on loading, and all of a sudden, boom!, kross would start throwing exceptions. I would run the debugging code I added to the ruby gc.c source to see what the ruby stack looks like when running kross.<br>
<br>This is the macro code I added to QtRuby (see qtruby/src/marshall_types.cpp):<br><br>// This is based on the SWIG SWIG_INIT_STACK and SWIG_RELEASE_STACK macros.<br>// If RUBY_INIT_STACK is only called when an embedded extension such as, a<br>
// Ruby Plasma plugin is loaded, then later the C++ stack can drop below where the <br>// Ruby runtime thinks the stack should start (ie the stack position when the <br>// plugin was loaded), and result in sys stackerror exceptions<br>
//<br>// TODO: While constructing the main class of a plugin when it is being loaded, <br>// there could be a problem when a custom virtual method is called or a slot is<br>// invoked, because RUBY_INIT_STACK will have aleady have been called from within <br>
// the krubypluginfactory code, and it shouldn&#39;t be called again.<br><br>#ifdef RUBY_EMBEDDED<br>#&nbsp; define QTRUBY_INIT_STACK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( nested_callback_count == 0 ) { RUBY_INIT_STACK } \<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nested_callback_count++;<br>#&nbsp; define QTRUBY_RELEASE_STACK nested_callback_count--;<br><br>static unsigned int nested_callback_count = 0;<br><br>#else&nbsp; /* normal non-embedded extension */<br><br>#&nbsp; define QTRUBY_INIT_STACK<br>
#&nbsp; define QTRUBY_RELEASE_STACK<br>#endif&nbsp; /* RUBY_EMBEDDED */<br><br>#ifdef RUBY_EMBEDDED<br><br>static VALUE funcall2_protect_id = Qnil;<br>static int funcall2_protect_argc = 0;<br>static VALUE * funcall2_protect_args = 0;<br>
<br>static VALUE<br>funcall2_protect(VALUE obj)<br>{<br>&nbsp;&nbsp;&nbsp; VALUE result = Qnil;<br>&nbsp;&nbsp;&nbsp; result = rb_funcall2(obj, funcall2_protect_id, funcall2_protect_argc, funcall2_protect_args);<br>&nbsp;&nbsp;&nbsp; return result;<br>}<br><br>#&nbsp; define QTRUBY_FUNCALL2(result, obj, id, argc, args) \<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int state = 0; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcall2_protect_id = id; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcall2_protect_argc = argc; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcall2_protect_args = args; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = rb_protect(funcall2_protect, obj, &amp;state); \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (state != 0) { \<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb_backtrace(); \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = Qnil; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>#else<br><br>#&nbsp; define QTRUBY_FUNCALL2(result, obj, id, argc, args) \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = rb_funcall2(obj, id, argc, args);<br><br>#endif<br><br>If QtRuby is built with a &#39;-DRUBY_EMBEDDED&#39; option (as for plasma), then rb_protect() is used to ensure that any ruby exceptions are caught and the process isn&#39;t terminated. Otherwise, funcall2() is called directly with no use of RUBY_INIT_STACK. Example usage:<br>
<br>&nbsp;&nbsp;&nbsp; VALUE result;<br>&nbsp;&nbsp;&nbsp; QTRUBY_INIT_STACK<br>&nbsp;&nbsp;&nbsp; QTRUBY_FUNCALL2(result, _obj, _slotname, _items - 1, _sp)<br>&nbsp;&nbsp;&nbsp; QTRUBY_RELEASE_STACK<br><br></div></div>-- Richard<br><br>