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

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

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

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

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

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

Версия 2.1.1:

Версия 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: %sn", result.String())
}

Source link

Total
0
Shares
Previous Post

Product analyst

Next Post

System Analyst

Related Posts