Как стать автором
Обновить

Запускаем скрипты Ruby из Go Lang

Время на прочтение3 мин
Количество просмотров2.3K

Для использования Ruby как скриптового языка, то есть как языка для встраивания, вроде lua, существует легковесная реализация Ruby под названием MRuby.

Для go удалось найти только одну стабильную библиотеку с биндингом к mruby. По умолчанию, она может собрать mruby версии 1.2.0 (2015 год выпуска), и можно попробовать сделать сборку вплоть до версии 1.4.1 (2018 год выпуска). Но актуальная версия mruby сейчас имеет версию 2.1.2 (2020 год). Есть форк с поддержкой версии mruby 2.1.0. Этот форк и будем использовать, что бы после небольших изменений получить в том числе версию 2.1.2.

В версиях старше 2.1.0 внесли как минимум следующие несовместимости на которые следует обратить внимание.

Версия 2.1.1:

  • Remove MRB_INT16 configuration option.

Версия 2.1.2

  • IO#readchar returns a UTF-8 character fragment instead of EOFError if EOF is reached in the middle of UTF-8 characters. (86271572) This behavior is different from CRuby, but it is a mruby specification that supports either ASCII or UTF-8 exclusively.

  • Remove mrb_run() from C APIs.

Для успешной сборки go-mruby критично удаление метода mrb_run. Как могут проявиться другие "Breaking Changes" пока не особо ясно. Теперь пошагово установка go-mruby:

  • Клонируем https://github.com/mrbgems/go-mruby/tree/mruby-2 в корень проекта и переключаемся на ветку mruby-2.

  • Удаляем go.mod и go.sum из директории go-mruby. Если их оставить, то go может не дать корректно импортировать модуль внутри программы. Возможно, зависит от версии go и надо покрутить настройки вендоринга, так как на протяжении нескольких версий в go поведение по умолчанию менялось. Ещё можно положить go-mruby в директорию vendor и исправить пути импортов.

  • Из файла mruby.go необходимо удалить метод Run(), а в тестах заменить все вызовы этого метода на RunWithContext().

  • В Makefile исправляем MRUBY_COMMIT на 2.1.2 - так мы получим актуальную версию mruby.

  • Запускаем make. Он сделает клон репозитория указанной версии mruby во вложенную директорию vendor и скомпилирует Си библиотеку libmruby.a.

На что ещё стоит обратить внимание. В форке в обязательном порядке занесён гем mruby-error как раз из за которого форк не был принят (https://github.com/mitchellh/go-mruby/pull/75). В mruby нет поддержки require и нельзя подключить модули в рантайме. Все необходимые модули необходимо подключить на этапе компиляции. Список доступных библиотек есть на странице http://mruby.org/libraries/, а в оригинальном файле mruby/build_config.rb есть пример подключения подключения стандартных и пользовательских библиотек. В mruby/examples/mrbgems можно подсмотреть примеры реализации собственных расширений, а в mruby/mrbgems стандартные библиотеки. Например, возможности метапрограммирования вынесены в отдельный гем mruby-metaprog.

Попробуем подключить поддержку json. Для этого необходимо в go-mruby/build_config.rb прописать библиотеку:

gem :github => 'iij/mruby-iijson'

Пример использования JSON.parse, при этом, как видим, опция symbolize_names этой библиотекой похоже не поддерживается.

func main() {
	mrb := mruby.NewMrb()
	defer mrb.Close()

	class := mrb.DefineClass("Example", nil)
	class.DefineClassMethod("json_value", func(m *mruby.Mrb, self *mruby.MrbValue) (mruby.Value, mruby.Value) {
		return mruby.String(`{"int":1, "array":["s1", "s2", {"nil": null}]}`), nil
	}, mruby.ArgsReq(1))

	result, err := mrb.LoadString(`JSON.parse(Example.json_value, {"symbolize_names" => true})`)
	if err != nil {
		panic(err.Error())
	}

	// Result: {"int"=>1, "array"=>["s1", "s2", {"nil"=>nil}]}
	fmt.Printf("Result: %s\n", result.String())
}
Теги:
Хабы:
-1
Комментарии0

Публикации

Истории

Работа

Программист Ruby
8 вакансий
Go разработчик
132 вакансии
Ruby on Rails
11 вакансий

Ближайшие события