Forum: Ruby Calling Ruby from Delphi

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
7dc696be30a508111b279187f674f11f?d=identicon&s=25 Rob Ram (_robz)
on 2008-12-24 08:22
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.
7956c3c7d7ef344265029e6b4b569b91?d=identicon&s=25 Huw Collingbourne (huw)
on 2008-12-25 22:40
You can connect Delphi Prism (Chrome/Oxgene) or C# or some other .NET
language with the Ruby interpreter using our free component, The Ruby
Connector. I haven't used Delphi 2009 (does that still have a .NET
version?) so can't comment specifically on that. The Ruby Connector
comes with a comprehensive manual and lots of sample code...

http://www.sapphiresteel.com/SapphireSteel-Downloads

best wishes
Huw Collingbourne

SapphireSteel Software
http://www.sapphiresteel.com
34a7615f38496a5dafbb3e6b721c435e?d=identicon&s=25 Mohit Sindhwani (Guest)
on 2008-12-26 06:41
(Received via mailing list)
Rob Ram wrote:
>  The above function is just some non-sense, but hopefully easy to use as
> ruby_script('embedded'); // or should it be ruby_script(‘ruby’)
> I found rb_funcall2 and VALUE is defined as:  typedef unsigned long
>            )
>
>
> 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.
7dc696be30a508111b279187f674f11f?d=identicon&s=25 Rob Ram (_robz)
on 2008-12-26 09:49
Huw Collingbourne wrote:
> You can connect Delphi Prism (Chrome/Oxgene) or C# or some other .NET
> language with the Ruby interpreter using our free component, The Ruby
> Connector. I haven't used Delphi 2009 (does that still have a .NET
> version?) so can't comment specifically on that. The Ruby Connector
> comes with a comprehensive manual and lots of sample code...
>
> http://www.sapphiresteel.com/SapphireSteel-Downloads
>
> best wishes
> Huw Collingbourne
>
> SapphireSteel Software
> http://www.sapphiresteel.com

Thank you for your reply.

I was successful calling Ruby from Delphi 2009. I used the Delphi API
found at: http://sourcepole.ch/2006/9/1/embedding-ruby-in-kylix-delphi .
This was originally written for Delphi 2006. However it will work with
Delphi 2009 with minor modifications. Delphi 2009 now supports Unicode
strings and user code strings must be re-cast to
ansiString/pAnsiString/ansiChar/pAnsiChar to be compatible with Ruby
strings.
Delphi 2009 is intended for native Windows development. There are other
versions of Delphi available for .net support.

The source code, “rubycomp-0.8-src.tar.gz”, provides a Delphi component
for easy evaluation. In my case however, I did not want to re-direct the
IO and removed the Ruby component. Otherwise, Ruby access is through
msvcrt-ruby18.dll. The source code provides Delphi files to access the
Ruby DLL. It’s basically ruby.h and other c++ files re-written for
Delphi.

To call Ruby functions from Delphi (in simplified terms):

1. First initialize Ruby.

2. Then use rb_require function to load the Ruby file.

3. Calling the “rb_eval_string” can easily access any function within
the Ruby file. For example:
rv := rb_eval_string(‘myFunction(a,b,c)’); // From the prior example.

4. Finally evaluate rv using:
    rtn := dl_Variant(rv); // where rtn is a variant array.

// multi-results from the prior example.
rv1 := rtn[0];
rv2 := rtn[1];
rv3 := rtn[2];

The dl_Variant function is found in uConv.pas (extracted from
rubycomp-0.8-src.tar.gz).

There may be better methods to call a Ruby function from Delphi, but
this does seem to work efficiently.
7dc696be30a508111b279187f674f11f?d=identicon&s=25 Rob Ram (_robz)
on 2008-12-26 09:53
Mohit Sindhwani wrote:
> 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.
>

Hi Mohit,
I will give it a try.
Thank You
34a7615f38496a5dafbb3e6b721c435e?d=identicon&s=25 Mohit Sindhwani (Guest)
on 2009-01-07 02:24
(Received via mailing list)
Mohit Sindhwani wrote:
> 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:
>>
> 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.

Rob, any luck with this?

Cheers,
Mohit.
1/7/2009 | 9:15 AM.
7dc696be30a508111b279187f674f11f?d=identicon&s=25 Rob Ram (_robz)
on 2009-01-15 08:34
Mohit Sindhwani wrote:
> Mohit Sindhwani wrote:
>> 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:
>>>
>> 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.
>
> Rob, any luck with this?
>
> Cheers,
> Mohit.
> 1/7/2009 | 9:15 AM.

I haven't had a chance to work on it yet; hopefully I will soon.
Thanks for your interest.
Rob
This topic is locked and can not be replied to.