Ruby интерпретатор встраивать в C-код - PullRequest
1 голос
/ 08 марта 2012

Я просто попробую простой пример из книги: у меня есть файл sum.rb:

class Summer
  def sum(max)
  raise "Invalid maximum #{max}" if max < 0
  (max*max + max)/2
  end
end

и файл embed_sum.c:

#include <stdio.h>
#include <ruby/ruby.h>
int main ( int argc, char ** argv) 
{
  VALUE result;
  ruby_sysinit(&argc, &argv);
  RUBY_INIT_STACK;
  ruby_init();
  ruby_init_loadpath();
  rb_require("sum");
  rb_eval_string("$summer = Summer.new");
  rb_eval_string("$result = $summer.sum(10)");
  result = rb_gv_get("result");
  printf("Result = %d\n", NUM2INT(result));
  return ruby_cleanup(0);
}

Я его скомпилируюс:

gcc -Wall -lruby -I/usr/include/ruby-1.9.1/  embed_sum.c -o embed_sum

Когда я запускаю ./embed_sum, это дает мне ошибку сегментации из первой строки rb_eval_string.моя версия ruby: ruby ​​1.9.3p125 (2012-02-16, редакция 34643) [x86_64-linux] в Archlinux.

В чем может быть проблема с этим примером?

1 Ответ

3 голосов
/ 08 марта 2012

Краткий ответ на вашу проблему - изменить строку rb_require("sum"); на rb_require("./sum");.Это изменение, представленное в Ruby 1.9.2, когда текущий каталог больше не находится на пути загрузки.

Более общая проблема заключается в том, как встроенный Ruby обрабатывает исключения.Книга Кирки (которую я считаю книгой, которую вы используете, использует похожий пример) гласит:

Если код Ruby вызывает исключение, и он не перехватывается, вашПрограмма C будет прервана.Чтобы преодолеть это, вам нужно сделать то, что делает переводчик, и защитить все вызовы, которые могут вызвать исключение.Это может привести к путанице.

Вам понадобится использовать функцию rb_protect для переноса вызовов в Ruby, которые могут вызвать исключение.Книга Кирки имеет пример этого.

...