From: Mohit Sindhwani Date: 2008-12-26T14:40:55+09:00 Subject: Re: Calling Ruby from Delphi Rob Ram wrote: > I want to call an embedded ruby function from Delphi 2009. A C or C++ > example is also ok. For example on the Ruby side: > > def myFunction(a,b,c) > rv1=a*b -c > rv2=a**2 + b**2 > rv3=b*c > return rv1, rv2, rv3 > end > > The above function is just some non-sense, but hopefully easy to use as > an example. MyExample.rb contains the above script. > > On the Delphi side: > > Starting with: > > fState := 0; > ruby_init; > ruby_init_loadpath; > rb_set_safe_level(0); > ruby_script('embedded'); // or should it be ruby_script(‘ruby’) > > > Ok now I have no clue as to what top do next. Somehow MyExample.rb must > be loaded. > > Maybe: > rb_load_file(‘MyExample.rb’) ??? > > Next call myFunction(a,b,c) ??? > > I found rb_funcall2 and VALUE is defined as: typedef unsigned long > VALUE > However I do not have documentation that explains the meaning of recv or > how to get the parameter for recv. > > > > VALUE rb_funcall2(VALUE recv, > ID mid, > int argc, > const VALUE * argv > ) > > > Any help or suggestions are appreciated. > Hi Rob, This is some of the stuff that I use in a Borland C++ Builder application - not sure if it helps you. The sequence is exaqctly the same as what the online version of PickAxe recommends, if I remember correctly. /* Initialize the Ruby VM */ void rubyVM_initialize() { ruby_init(); ruby_init_loadpath(); ruby_script("embedded"); //set a name that the script will use return; } /* Finalize the Ruby VM */ void rubyVM_finalize() { ruby_finalize(); } /* Functions to call the functions in Ruby script */ static VALUE wrap_sum(VALUE args) { VALUE *values = (VALUE *)args; VALUE summer = values[0]; VALUE max = values[1]; //object, function, count?, argument return rb_funcall(summer, id_sum, 1, max); } static VALUE protected_sum(VALUE summer, VALUE max) { int error; VALUE args[2]; VALUE result; args[0] = summer; args[1] = max; result = rb_protect(wrap_sum, (VALUE)args, &error); return error ? Qnil : result; } /* Sample script execution */ int run_a_script(void) { int value; int *next = Values; char output[200]; /* Call ruby VM init first */ rubyVM_initialize(); rb_require ("sum.rb"); //script that you want to use /* Instantiate the class (Summer) you want to use */ VALUE summer = rb_class_new_instance(0, 0, rb_const_get(rb_cObject, rb_intern("Summer"))); /* Access the function in that class */ /* Note id_sum is a global variable below */ id_sum = rb_intern("sum"); //the function while (value = *next++) { /* The next line does the hard work through 2 functions */ VALUE result = protected_sum(summer, INT2NUM(value)); if (NIL_P(result)) { sprintf(output,"Sum to %d doesn't compute!\n", value); } else { sprintf(output,"Sum to %d is %d\n", value, NUM2INT(result)); } //MessageBox(NULL,output,"Ruby result!",MB_OK); } //rubyVM_finalize(); //return; } I'm sorry I'm in a bit of a rush, but do ask again - I'll reply with more details if this doesn't help. Essentially, I think what you need is: * rb_require ("sum.rb"); //script that you want to use * VALUE result = protected_sum(summer, INT2NUM(value)); * See the wrapped functions to pack the parameters and safely call the function * rb_funcall(summer, id_sum, 1, max); // I think this is object, function_number, # of parameters, max Hopefully this will help: http://whytheluckystiff.net/ruby/pickaxe/html/ext_ruby.html Cheers Mohit.