在C++应用程序中嵌入Ruby解释器

18
我希望将Ruby用作我的游戏引擎的脚本语言。我已经找到了通常的文章,介绍如何从C++代码中调用Ruby类和反之亦然(例如在这里),但我无法看出如何使用那种方式来实现我想要的...

我的引擎目前使用我自己用Flex和Bison编写的小语言,以及一个小型基于堆栈的虚拟机。脚本不总是从头到尾运行,例如它们有时包括像“等待2秒”或“等待字符完成行走”这样的命令,因此调度程序跟踪每个脚本的状态和指令指针,并知道何时恢复它们等等。

因此,似乎我确实需要某种嵌入式Ruby解释器,可以对其进行一定程度的控制,而不仅仅是调用Ruby方法。或者我只是思路不清,错过了什么?

我正在使用Microsoft Visual C++,因此最理想的解决方案应该能够轻松编译。


1
如果有人好奇我最终做了什么...我使用了具有协程功能的Lua,它似乎运行得非常好。 - andygeers
5个回答

28

这里有一个包含错误处理的示例。

#include <iostream>
#include <ruby.h>

using namespace std;

int main(void)
{
  ruby_init();
  ruby_init_loadpath();
  int status;
  rb_load_protect(rb_str_new2("./test.rb"), 0, &status);
  if (status) {
    VALUE rbError = rb_funcall(rb_gv_get("$!"), rb_intern("message"), 0);
    cerr << StringValuePtr(rbError) << endl;
  };
  ruby_finalize();
  return status;
}

1
这是一个部分回答,但据我所知,它仍然没有涉及暂停脚本的问题? - andygeers

4

你走在正确的道路上。关键是要做类似于你发布的链接中嵌入概念部分的内容。简单来说,它不过是:

ruby_init();
ruby_script("some_script");

你可能需要从main.c中复制所有的#ifdef内容,以确保一切正常运行。之后,你需要构建一个API来暴露你想要公开的C ++函数,并根据你的设计将其多线程化。

这似乎仍然没有解决如何将其中一个脚本置于睡眠模式的问题,例如 - 调度方面的问题。 - andygeers
链接 404,请修复。 - ice1000

4
你可以重新设计脚本的工作方式以适应脚本引擎,而不是试图让引擎与原始脚本范例一起工作。因此,如果你有以下内容:
proc:
  action 1
  action 2
  sleep a bit
  action 3
end

如果需要在sleep行上暂停脚本,请执行以下操作:

proc
  action1
  action2
  set timer (time, callback_proc)
end

callback_proc
  action3
end

这使得脚本引擎可以整洁地完成每个方法。宿主端不需要进行太多更改 - 每个版本都需要某种形式的事件系统,可以重新启动脚本引擎。


3

2
对于未来的读者,C++指南网站已经重新组织。新的URL是:http://aeditor.rubyforge.org/ruby_cplusplus/index.html - Iain
4
不幸的是,Ruby Forge和我的Opera都已关闭,因此既无法获得指南也无法获取文章。原文意思已保持不变,语言更通俗易懂。 - Marlin Pierce

1

我认为你需要使用Ruby的线程。我已经深入研究了Ruby线程代码,我知道(在pthreads可用的情况下)sleep是使用pthread_cond_timedwait以非阻塞方式实现的。这将解除解释器的阻塞,以便其他线程可以继续执行。

当涉及与Ruby解释器交互时,你自己的代码将不得不尊重Ruby的线程。他们在Ruby中仍然有全局VM锁,这意味着你在没有自己的锁的情况下修改解释器中的任何内容时应该小心。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接