В прошлых частях(часть 1,часть 2) мы рассмотрели использование С для ускорения или расширения Ruby. Сейчас же мы узнаем как использовать Ruby интерпретатор в программах, написанных на С/С++.
В некоторых приложениях возникает необходимость во встроенном языке, для более тонкой настройки или для написания расширений без перекомпиляции. Ruby очень хорошо подходит для этой цели, т.к. имеет простое и удобное API для втраивания в C/C++ приложения. Например Google SketchUp использует Ruby в качестве скриптового языка.
Давайте рассмотрим как встроить Ruby в наши С/С++ приложения.
Начнем с рассмотрения функции
Давайте рассмотрим простой пример — програма для вычисления выражений. Для простоты у нас в выражениях будет только две переменные.
Пример работы приложения, входные данные:
Результат:
Посмотрим код:
Примечание: про тип данных VALUE, макросы INT2NUM и т.п., и более подробно про работу с Ruby C API смотрите в части 2
В данном примере мы считали с клавиатуры две переменные и выражение с ними. Затем, на основе этих переменных, создали глобальные Ruby переменные и, с помощью метода
В итоге, с помощью метода
Теперь перейдем к загрузке и выполнению скриптов на Ruby.
Рассмотрим такой пример: нам нужно получать хэш строки по пользовательскому алгоритму. Сценарий работы такой, пользователь создает файл alg.rb и реализует в нем алгоритм хэширования. В нашей програме мы загружаем пользовательский скрипт, передаем ему строку для хэширования, выполняем скрипт и печатаем результат.
Посмотрим код:
Теперь в файле alg.rb мы можем реализовывать какие угодно алгоритмы хэширования.
Например, к количество пробелов в строке(не очень удачный хэш:)):
или сумма всех символов в шестнадцатеричном виде:
или же md5, с помощью стандартной библиотеки:
Теперь о компиляции приложений со встроенным Ruby, на пример gcc:
либо:
Для компиляции в *nix системах нужно поставить пакет ruby-dev, например так:
В некоторых приложениях возникает необходимость во встроенном языке, для более тонкой настройки или для написания расширений без перекомпиляции. Ruby очень хорошо подходит для этой цели, т.к. имеет простое и удобное API для втраивания в C/C++ приложения. Например Google SketchUp использует Ruby в качестве скриптового языка.
Давайте рассмотрим как встроить Ruby в наши С/С++ приложения.
Начнем с рассмотрения функции
rb_eval_string
, которая выполняет строку с Ruby кодом.Давайте рассмотрим простой пример — програма для вычисления выражений. Для простоты у нас в выражениях будет только две переменные.
Пример работы приложения, входные данные:
($a+$b)*$a-$b 2 3
Результат:
($a+$b)*$a-$b = 7
Посмотрим код:
#include <ruby.h> #include <stdio.h> int main() { ruby_init(); //инициализация интерпретатора int a = 0; int b = 0; char expr[256]; //читаем выражение и две переменные scanf("%s", &expr); scanf("%d", &a); scanf("%d", &b); //создаем Ruby переменные VALUE r_a = INT2NUM(a); VALUE r_b = INT2NUM(b); //и делаем их доступными в интерпретаторе rb_define_variable("$a", &r_a); rb_define_variable("$b", &r_b); //выполняем выражение и выводим результат VALUE res = rb_eval_string(expr); printf("%s = %d\n", expr, NUM2INT(res)); return 0; }
Примечание: про тип данных VALUE, макросы INT2NUM и т.п., и более подробно про работу с Ruby C API смотрите в части 2
В данном примере мы считали с клавиатуры две переменные и выражение с ними. Затем, на основе этих переменных, создали глобальные Ruby переменные и, с помощью метода
rb_define_variable
, сделали их доступными в интерпретаторе.В итоге, с помощью метода
rb_eval_string
, мы выполнили выражение и вывели его результат на экран.Теперь перейдем к загрузке и выполнению скриптов на Ruby.
Рассмотрим такой пример: нам нужно получать хэш строки по пользовательскому алгоритму. Сценарий работы такой, пользователь создает файл alg.rb и реализует в нем алгоритм хэширования. В нашей програме мы загружаем пользовательский скрипт, передаем ему строку для хэширования, выполняем скрипт и печатаем результат.
Посмотрим код:
#include <ruby.h> #include <stdio.h> int main() { ruby_init(); //инициализация интерпретатора ruby_init_loadpath(); //возможность подключать стандартные библиотеки, например require 'MD5' VALUE res = rb_str_new2("some test string"); //наша тестовая строка rb_define_variable("$res", &res); //делаем ее доступной скрипту rb_load_file("alg.rb"); //загружаем файл с алгоритмом //выполняем скрипт и выводим результат ruby_exec(); printf("%s\n", StringValuePtr(res)); return 0; }
Теперь в файле alg.rb мы можем реализовывать какие угодно алгоритмы хэширования.
Например, к количество пробелов в строке(не очень удачный хэш:)):
hash = 0 $res.split(//).each {|c| hash += 1 if c == " "} $res = hash.to_s
или сумма всех символов в шестнадцатеричном виде:
hash = 0 $res.split(//).each {|c| hash += c[0]} $res = hash.to_s(16)
или же md5, с помощью стандартной библиотеки:
require "md5" $res = MD5.hexdigest($res)
Теперь о компиляции приложений со встроенным Ruby, на пример gcc:
gcc test.c -o test -I<папка с ruby.h> -lruby
либо:
gcc test.c -o test -I<папка с ruby.h> -lruby1.8
Для компиляции в *nix системах нужно поставить пакет ruby-dev, например так:
sudo apt-get install ruby1.8-dev