gpt4 book ai didi

c++ - 在循环中从 C++ 调用 Ruby 函数导致 "stack level too deep"

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:59:48 24 4
gpt4 key购买 nike

我正在尝试从 C++ 运行 Ruby 代码块。我有两个 Ruby 函数,一个叫做 Init(),一个叫做 Loop()。我遇到的问题是,在我从 SystemStackError 得到“堆栈级别太深”之前,我只能 Loop() 很多次。据我所知,我的 Ruby 代码不是递归的。如您所见,到目前为止,这段 Ruby 代码仅用于概念验证,除了调试风格的内容和面板上的闪烁灯外,什么都没有加载。这是 Ruby 代码:

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

我在 C++ 中的 Panel 实现是:

ruby_init();
VALUE cPanel;
cPanel = rb_define_class( "Panel", rb_cObject );
rb_define_singleton_method( cPanel, "new", (RubyMethod*)&StaticRubyNew, 0 );
rb_define_method( cPanel, "Debug", (RubyMethod*)&StaticRubyDebug, 0 );
rb_define_method( cPanel, "Extinguish", (RubyMethod*)&StaticRubyExtinguish, 1 );
rb_define_method( cPanel, "Illuminate", (RubyMethod*)&StaticRubyIlluminate, 1 );

我调用脚本函数如下:

rb_eval_string( program );

rb_funcall( Qnil, rb_intern( "Init" ), 0, NULL );

// In a 200ms loop:
rb_funcall( Qnil, rb_intern( "Loop" ), 0, NULL );

直到我编写了一个(可疑的)实现:

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<char*>(s) );
return tdata;
}

RubyMark 和 RubyFree 没有做任何事情,RubyDebug、RubyIlluminate 等也没有为手头的问题做任何显着的事情。

我已经尝试将 Init 和 Loop 包装在一个类中作为类方法,这样我就可以用一个真正的接收器调用 rb_funcall() 。我尝试通过 rb_protect() 调用来获取回溯(回溯显示为空)。在线似乎没有任何内容可以将脚本作为字符串加载,所以 rb_eval_string() 是一个猜测。 rb_load_file() 也不起作用。

为什么这会导致堆栈问题?我可以编辑我的 Ruby 脚本,添加或删除代码,并且在执行不同数量的循环后堆栈崩溃。我可以执行的循环数与行数没有明显关系。如果我删除一行,我可能会得到 45 个循环。如果我删除另一个,我可能会超过 2000。我做错了什么?

根据下面的响应再编写一些代码——这是为 Ruby API 调用提供 C++ 方法(需要 C 风格的函数):

typedef VALUE (RubyMethod)(...);
extern "C" /*static*/ VALUE StaticRubyNew( VALUE self )
{
return MainWidget::M_this->RubyNew( self );
}

最佳答案

好的,所以我减少了它,直到我得到一个类似于我的 C 实现的工作版本,但问题与 C++ 和 C 无关。上面没有显示的(因为我认为它不相关)是这是一个 Qt 应用程序,我有两个槽——一个用于初始化 ruby​​ 和加载程序,另一个用于调用循环函数。后一个插槽从计时器(不相关)中重复调用。当我将 ruby​​_init() 移出槽并移入 main() 时,突破发生了。在谷歌上搜索发现这个有趣的 answer :

来自 Matz 自己,“任何 Ruby 对象都不应从低于调用 ruby​​_init() 时的位置。”

所以发生的事情是,当每个槽被调用时,它们在堆栈中的不确定位置,而如果你从 main() 调用 ruby​​_init() 然后开始运行 Qt 的事件循环,你肯定会在在堆栈上的正确位置执行 rb_funcall() 等。

关于c++ - 在循环中从 C++ 调用 Ruby 函数导致 "stack level too deep",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4082989/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com