Embedding a Ruby interpreter in a C++ app

你说的曾经没有我的故事 提交于 2019-12-28 11:46:08

问题


I'm hoping to use Ruby as a scripting language for my game engine. I've found the usual articles describing how to call Ruby classes from C++ code and vice versa (e.g. here) but I can't quite see how to do what I want with that way of working...

My engine currently uses a little language I wrote myself with Flex and Bison, and a little stack based virtual machine. Scripts don't always run right through from start to finish, for instance they sometimes includes commands like "sleep for 2 seconds" or "wait until character has finished walking", so the scheduler keeps tabs on the status of each script and an instruction pointer, and knows when to resume them, and so on.

So it seems that I really need some kind of embedded Ruby interpreter that I can exercise a certain degree of control over, rather than simply calling Ruby methods. Or am I just being obtuse and missing something?

I'm working in Microsoft Visual C++, so ideally any solution would compile nice and easily in that.


回答1:


Here's an example including error handling.

#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;
}



回答2:


You're on the right track. The key is to do something similar to the section on Embedding Concepts in the link you posted. In simple terms it's little more than:

ruby_init();
ruby_script("some_script");

You may need to copy over all the #ifdef stuff from main.c to get everything working. From then it's a matter of building an API to your C++ functions you want to expose, and depending on your design, multi-threading the thing.




回答3:


You could always re-design the way the scripts work to suit the script engine rather than trying to get the engine to work with the original scripting paradigms.

So, if you had this:

proc:
  action 1
  action 2
  sleep a bit
  action 3
end

which would require the script to be suspended on the sleep line, do this:

proc
  action1
  action2
  set timer (time, callback_proc)
end

callback_proc
  action3
end

which lets the scripting engine finish each method neatly. It wouldn't need many changes to the hosting side - each version requires some form of event system which can restart the script engine.




回答4:


There is a guide about how to embed ruby into a C++ application. That may be helpful. Otherwise go to the Ruby documentation. The Embed Ruby in C article may be helpful, too.




回答5:


I think what your going to want to do is use Ruby's threads. I've done a fair bit of digging through the Ruby threading code and I know that (where pthreads is available) sleep is implemented in a non-blocking fashion using pthread_cond_timedwait. This unblocks the interpreter so that other threads can continue execution.

Your own code is going to have to respect Ruby's threads when it comes to interacting with the Ruby interpreter. They've still got a Global VM Lock in Ruby which means you should be careful about modifying anything in the interpreter without having the lock yourself.



来源:https://stackoverflow.com/questions/626333/embedding-a-ruby-interpreter-in-a-c-app

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!