Встраивание интерпретатора Ruby в приложение C ++ - PullRequest
19 голосов
/ 09 марта 2009

Я надеюсь использовать Ruby в качестве языка сценариев для моего игрового движка. Я нашел обычные статьи, описывающие, как вызывать классы Ruby из кода C ++ и наоборот (например, здесь ), но я не совсем понимаю, как сделать то, что я хочу, таким способом работы ...

В настоящее время мой движок использует небольшой язык, который я написал для Flex и Bison, и небольшую виртуальную машину на основе стека. Скрипты не всегда выполняются сразу от начала до конца, например, они иногда включают в себя такие команды, как «спать в течение 2 секунд» или «ждать, пока персонаж закончил ходить», поэтому планировщик следит за состоянием каждого сценария и инструкцией указатель и знает, когда их возобновить и т. д.

Так что, похоже, мне действительно нужен какой-то встроенный интерпретатор Ruby, который я могу контролировать в определенной степени, а не просто вызывать методы Ruby. Или я просто тупой и что-то упускаю?

Я работаю в Microsoft Visual C ++, поэтому в идеале любое решение будет легко и просто компилироваться.

Ответы [ 5 ]

29 голосов
/ 28 октября 2011

Вот пример, включающий обработку ошибок.

#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;
}
4 голосов
/ 09 марта 2009

Вы всегда можете изменить дизайн сценариев так, чтобы они соответствовали обработчику сценариев, а не пытаться заставить механизм работать с оригинальными парадигмами сценариев.

Итак, если у вас было это:

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

, что потребовало бы приостановки работы сценария в строке сна, сделайте следующее:

proc
  action1
  action2
  set timer (time, callback_proc)
end

callback_proc
  action3
end

, что позволяет обработчику сценариев аккуратно завершать каждый метод. Это не потребовало бы много изменений на стороне хостинга - каждая версия требует некоторой формы системы событий, которая может перезапустить механизм сценариев.

4 голосов
/ 09 марта 2009

Вы на правильном пути. Ключ должен сделать что-то похожее на раздел Embedding Concepts в ссылке, которую вы разместили. Проще говоря, это немного больше, чем:

ruby_init();
ruby_script("some_script");

Вам может понадобиться скопировать все файлы #ifdef из main.c , чтобы все заработало. С этого момента речь идет о создании API для ваших функций C ++, которые вы хотите представить, и в зависимости от вашего дизайна, многопоточности.

3 голосов
/ 09 апреля 2009

Существует руководство о том, как встраивать ruby ​​в приложение C ++. Это может быть полезно. В противном случае перейдите к документации Ruby . Статья Embed Ruby in C также может быть полезна.

1 голос
/ 14 марта 2011

Я думаю, что вы захотите сделать, это использовать темы Руби. Я довольно много покопался в поточном коде Ruby и знаю, что (где есть pthreads) сон реализован неблокирующим образом с использованием pthread_cond_timedwait. Это разблокирует интерпретатор, чтобы другие потоки могли продолжить выполнение.

Ваш собственный код должен учитывать потоки Ruby, когда дело доходит до взаимодействия с интерпретатором Ruby. У них все еще есть глобальная блокировка виртуальной машины в Ruby, что означает, что вы должны быть осторожны при изменении чего-либо в интерпретаторе, не имея блокировки самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...