Embedded Ruby Question

Discussion in 'Ruby' started by Brian Campbell, Aug 2, 2006.

  1. Hi all,

    I want to embed Ruby in my C++ application. I'd like to read one or more
    Ruby scripts stored in my RDBMS, pass the Ruby script as a string (not a
    file name) to the interpreter, and have it execute the code. Is this
    possible? If so, is there a URL that describes how to do this or shows an
    example?

    Thanks!

    -Brian

    --------------------
    Brian E Campbell
    Brian Campbell, Aug 2, 2006
    #1
    1. Advertising

  2. There's a good section on embedding Ruby in the Pickaxe 2. You have to
    be extremely careful with some aspects of it, especially if you use
    threads (the Ruby interpreter is not currently thread safe).

    Brian Campbell wrote:
    > Hi all,
    >
    > I want to embed Ruby in my C++ application. I'd like to read one or more
    > Ruby scripts stored in my RDBMS, pass the Ruby script as a string (not a
    > file name) to the interpreter, and have it execute the code. Is this
    > possible? If so, is there a URL that describes how to do this or shows an
    > example?
    >
    > Thanks!
    >
    > -Brian
    >
    > --------------------
    > Brian E Campbell
    >
    Timothy Goddard, Aug 2, 2006
    #2
    1. Advertising

  3. Hi Timothy,

    Thanks for the reply!

    Yes, I have the Pickaxe 2. Unfortunately, it doesn't describe/document,
    what I need to do. It describes how to embed the interpreter, call/execute
    Ruby from an existing file, extend Ruby via C/C++, but it does not describe
    how to pass a string that is Ruby code from C++ to the interpreter and have
    it execute. That's what I need.

    Thanks.

    -Brian

    --------------------
    Brian E Campbell





    >From: "Timothy Goddard" <>
    >Reply-To:
    >To: (ruby-talk ML)
    >Subject: Re: Embedded Ruby Question
    >Date: Wed, 2 Aug 2006 09:50:10 +0900
    >
    >There's a good section on embedding Ruby in the Pickaxe 2. You have to
    >be extremely careful with some aspects of it, especially if you use
    >threads (the Ruby interpreter is not currently thread safe).
    >
    >Brian Campbell wrote:
    > > Hi all,
    > >
    > > I want to embed Ruby in my C++ application. I'd like to read one or

    >more
    > > Ruby scripts stored in my RDBMS, pass the Ruby script as a string (not a
    > > file name) to the interpreter, and have it execute the code. Is this
    > > possible? If so, is there a URL that describes how to do this or shows

    >an
    > > example?
    > >
    > > Thanks!
    > >
    > > -Brian
    > >
    > > --------------------
    > > Brian E Campbell
    > >

    >
    >
    Brian Campbell, Aug 2, 2006
    #3
  4. Brian Campbell

    Guest

    As a matter of fact, ruby's interpreter accepts the switch '-e' to
    execute any string following it as ruby source code.

    for instance, when you entered as following,
    ruby -e "puts 5"
    the console would output 5.

    you may execute such shell command in C/C++.
    may it be of help.

    Brian Campbell wrote:
    > Hi Timothy,
    >
    > Thanks for the reply!
    >
    > Yes, I have the Pickaxe 2. Unfortunately, it doesn't describe/document,
    > what I need to do. It describes how to embed the interpreter, call/execute
    > Ruby from an existing file, extend Ruby via C/C++, but it does not describe
    > how to pass a string that is Ruby code from C++ to the interpreter and have
    > it execute. That's what I need.
    >
    > Thanks.
    >
    > -Brian
    >
    > --------------------
    > Brian E Campbell
    >
    >
    >
    >
    >
    > >From: "Timothy Goddard" <>
    > >Reply-To:
    > >To: (ruby-talk ML)
    > >Subject: Re: Embedded Ruby Question
    > >Date: Wed, 2 Aug 2006 09:50:10 +0900
    > >
    > >There's a good section on embedding Ruby in the Pickaxe 2. You have to
    > >be extremely careful with some aspects of it, especially if you use
    > >threads (the Ruby interpreter is not currently thread safe).
    > >
    > >Brian Campbell wrote:
    > > > Hi all,
    > > >
    > > > I want to embed Ruby in my C++ application. I'd like to read one or

    > >more
    > > > Ruby scripts stored in my RDBMS, pass the Ruby script as a string (not a
    > > > file name) to the interpreter, and have it execute the code. Is this
    > > > possible? If so, is there a URL that describes how to do this or shows

    > >an
    > > > example?
    > > >
    > > > Thanks!
    > > >
    > > > -Brian
    > > >
    > > > --------------------
    > > > Brian E Campbell
    > > >

    > >
    > >
    , Aug 2, 2006
    #4
  5. Brian Campbell

    Guest

    As a matter of fact, ruby's interpreter accepts the switch '-e' to
    execute any string following it as ruby source code.

    for instance, when you entered as following,
    ruby -e "puts 5"
    the console would output 5.

    you may execute such shell command in C/C++.
    may it be of help.

    Brian Campbell wrote:
    > Hi Timothy,
    >
    > Thanks for the reply!
    >
    > Yes, I have the Pickaxe 2. Unfortunately, it doesn't describe/document,
    > what I need to do. It describes how to embed the interpreter, call/execute
    > Ruby from an existing file, extend Ruby via C/C++, but it does not describe
    > how to pass a string that is Ruby code from C++ to the interpreter and have
    > it execute. That's what I need.
    >
    > Thanks.
    >
    > -Brian
    >
    > --------------------
    > Brian E Campbell
    >
    >
    >
    >
    >
    > >From: "Timothy Goddard" <>
    > >Reply-To:
    > >To: (ruby-talk ML)
    > >Subject: Re: Embedded Ruby Question
    > >Date: Wed, 2 Aug 2006 09:50:10 +0900
    > >
    > >There's a good section on embedding Ruby in the Pickaxe 2. You have to
    > >be extremely careful with some aspects of it, especially if you use
    > >threads (the Ruby interpreter is not currently thread safe).
    > >
    > >Brian Campbell wrote:
    > > > Hi all,
    > > >
    > > > I want to embed Ruby in my C++ application. I'd like to read one or

    > >more
    > > > Ruby scripts stored in my RDBMS, pass the Ruby script as a string (not a
    > > > file name) to the interpreter, and have it execute the code. Is this
    > > > possible? If so, is there a URL that describes how to do this or shows

    > >an
    > > > example?
    > > >
    > > > Thanks!
    > > >
    > > > -Brian
    > > >
    > > > --------------------
    > > > Brian E Campbell
    > > >

    > >
    > >
    , Aug 2, 2006
    #5
  6. On Aug 1, 2006, at 9:28 PM, Brian Campbell wrote:

    > Hi Timothy,
    >
    > Thanks for the reply!
    >
    > Yes, I have the Pickaxe 2. Unfortunately, it doesn't describe/
    > document, what I need to do. It describes how to embed the
    > interpreter, call/execute Ruby from an existing file, extend Ruby
    > via C/C++, but it does not describe how to pass a string that is
    > Ruby code from C++ to the interpreter and have it execute. That's
    > what I need.
    >
    > Thanks.
    >

    One of the best sources of documentation for C extensions is
    README.EXT in the source distribution. Here is the relevant section
    for what you want to do:

    2.2.1 Evaluate Ruby Programs in a String

    The easiest way to use Ruby's functionality from a C program is to
    evaluate the string as Ruby program. This function will do the job.

    VALUE rb_eval_string(const char *str)

    Evaluation is done under the current context, thus current local
    variables
    of the innermost method (which is defined by Ruby) can be accessed.


    > -Brian
    >
    > --------------------
    > Brian E Campbell
    >
    >
    >
    >
    >
    >> From: "Timothy Goddard" <>
    >> Reply-To:
    >> To: (ruby-talk ML)
    >> Subject: Re: Embedded Ruby Question
    >> Date: Wed, 2 Aug 2006 09:50:10 +0900
    >>
    >> There's a good section on embedding Ruby in the Pickaxe 2. You
    >> have to
    >> be extremely careful with some aspects of it, especially if you use
    >> threads (the Ruby interpreter is not currently thread safe).
    >>
    >> Brian Campbell wrote:
    >> > Hi all,
    >> >
    >> > I want to embed Ruby in my C++ application. I'd like to read

    >> one or more
    >> > Ruby scripts stored in my RDBMS, pass the Ruby script as a

    >> string (not a
    >> > file name) to the interpreter, and have it execute the code. Is

    >> this
    >> > possible? If so, is there a URL that describes how to do this

    >> or shows an
    >> > example?
    >> >
    >> > Thanks!
    >> >
    >> > -Brian
    >> >
    >> > --------------------
    >> > Brian E Campbell
    >> >

    >>
    >>

    >
    >
    >
    Logan Capaldo, Aug 2, 2006
    #6
  7. Logan,

    Excellent! This is exactly what I'm after. Thanks!

    -Brian



    --------------------
    Brian E Campbell






    >From: Logan Capaldo <>
    >Reply-To:
    >To: (ruby-talk ML)
    >Subject: Re: Embedded Ruby Question
    >Date: Wed, 2 Aug 2006 12:55:46 +0900
    >
    >
    >On Aug 1, 2006, at 9:28 PM, Brian Campbell wrote:
    >
    >>Hi Timothy,
    >>
    >>Thanks for the reply!
    >>
    >>Yes, I have the Pickaxe 2. Unfortunately, it doesn't describe/ document,
    >>what I need to do. It describes how to embed the interpreter,
    >>call/execute Ruby from an existing file, extend Ruby via C/C++, but it
    >>does not describe how to pass a string that is Ruby code from C++ to the
    >>interpreter and have it execute. That's what I need.
    >>
    >>Thanks.
    >>

    >One of the best sources of documentation for C extensions is README.EXT in
    >the source distribution. Here is the relevant section for what you want to
    >do:
    >
    >2.2.1 Evaluate Ruby Programs in a String
    >
    >The easiest way to use Ruby's functionality from a C program is to
    >evaluate the string as Ruby program. This function will do the job.
    >
    > VALUE rb_eval_string(const char *str)
    >
    >Evaluation is done under the current context, thus current local variables
    >of the innermost method (which is defined by Ruby) can be accessed.
    >
    >
    >>-Brian
    >>
    >>--------------------
    >>Brian E Campbell
    >>
    >>
    >>
    >>
    >>
    >>>From: "Timothy Goddard" <>
    >>>Reply-To:
    >>>To: (ruby-talk ML)
    >>>Subject: Re: Embedded Ruby Question
    >>>Date: Wed, 2 Aug 2006 09:50:10 +0900
    >>>
    >>>There's a good section on embedding Ruby in the Pickaxe 2. You have to
    >>>be extremely careful with some aspects of it, especially if you use
    >>>threads (the Ruby interpreter is not currently thread safe).
    >>>
    >>>Brian Campbell wrote:
    >>> > Hi all,
    >>> >
    >>> > I want to embed Ruby in my C++ application. I'd like to read one or
    >>>more
    >>> > Ruby scripts stored in my RDBMS, pass the Ruby script as a string
    >>>(not a
    >>> > file name) to the interpreter, and have it execute the code. Is this
    >>> > possible? If so, is there a URL that describes how to do this or
    >>>shows an
    >>> > example?
    >>> >
    >>> > Thanks!
    >>> >
    >>> > -Brian
    >>> >
    >>> > --------------------
    >>> > Brian E Campbell
    >>> >
    >>>
    >>>

    >>
    >>
    >>

    >
    >
    Brian Campbell, Aug 2, 2006
    #7
  8. Brian Campbell

    Guest

    Hi,

    At Wed, 2 Aug 2006 12:55:46 +0900,
    Logan Capaldo wrote in [ruby-talk:205673]:
    > VALUE rb_eval_string(const char *str)


    It's not exception safe. Use rb_eval_string_protect() for
    embedded use.

    --
    Nobu Nakada
    , Aug 2, 2006
    #8
  9. Brian Campbell

    Timothy Byrd Guest

    Brian Campbell wrote:

    > I want to embed Ruby in my C++ application.


    Here is some sample code I'd come up with (for 1.8.2, I think). You
    may need to tweak it a bit.

    -- Timothy

    // r_in_c.cpp : Sample program for embedding Ruby in C.
    //

    //#include "stdafx.h"
    #include <tchar.h>
    #include "stdio.h"
    #include <string>

    #pragma warning(disable: 4312)

    #include "ruby.h"
    //#include "st.h"

    void print_ruby_value(int v, int indent, const char* str)
    {
    VALUE val = (VALUE)(v);
    int type = TYPE(v);
    #if 1
    switch (type) {
    case T_FIXNUM:
    printf("%*s`%s` ==> fixnum, value = %d\n", indent, "", str,
    FIX2INT(v));
    break;
    case T_NIL:
    printf("%*s`%s` ==> nil\n", indent, "", str);
    break;
    case T_FALSE:
    printf("%*s`%s` ==> false\n", indent, "", str);
    break;
    case T_TRUE:
    printf("%*s`%s` ==> true\n", indent, "", str);
    break;
    case T_UNDEF:
    printf("%*s`%s` ==> undef\n", indent, "", str);
    break;
    case T_SYMBOL:
    printf("%*s`%s` ==> symbol (%d)\n", indent, "", str,
    SYM2ID(v));
    break;
    case T_STRING:
    printf("%*s`%s` ==> string `%*s`\n", indent, "", str,
    RSTRING(v)->len, RSTRING(v)->ptr);
    break;
    case T_FLOAT:
    printf("%*s`%s` ==> float `%f`\n", indent, "", str,
    RFLOAT(v)->value);
    break;
    case T_BIGNUM:
    {
    VALUE s = rb_String(val);
    printf("%*s`%s` ==> bignum `%*s`\n", indent, "", str,
    RSTRING(s)->len, RSTRING(s)->ptr);
    }
    break;
    case T_REGEXP:
    printf("%*s`%s` ==> regexp `%*s`\n", indent, "", str,
    RREGEXP(v)->len, RREGEXP(v)->str);
    break;
    case T_ARRAY:
    {
    char buffer[20];
    long len = RARRAY(v)->len;
    VALUE* ptr = RARRAY(v)->ptr;
    printf("%*s`%s` ==> array (%d):\n", indent, "", str, len);
    for (long i = 0; i < RARRAY(v)->len; ++i)
    {
    sprintf(buffer, "a[%d]", i);
    print_ruby_value(ptr, indent+4, "default value");
    }
    }
    break;
    case T_HASH:
    {
    RHash* h = RHASH(v);
    printf("%*s`%s` ==> hash (iter_lev %d):\n", indent, "", str,
    h->iter_lev);
    print_ruby_value(h->ifnone, indent+4, "not found value");

    struct st_table *tbl = h->tbl;;
    printf("%*sbins = %d, entries = %d\n", indent+4, "",
    tbl->num_bins, tbl->num_entries);
    }
    break;
    default:
    printf("%*s`%s` ==> class %d\n", indent, "", str, type);
    break;
    }
    #else
    switch (type) {
    case T_NIL:
    printf("%*s`%s` ==> nil\n", indent, "", str);
    break;
    case T_ARRAY:
    val = rb_ary_join(val, rb_str_new2(", "));
    printf("%*s`%s` ==> type(%d) `[%*s]`\n", indent, "", str, type,
    RSTRING(val)->len, RSTRING(val)->ptr);
    break;
    case T_REGEXP:
    val = rb_String(val);
    printf("%*s`%s` ==> type(%d) `/%*s/`\n", indent, "", str, type,
    RSTRING(val)->len, RSTRING(val)->ptr);
    break;
    default:
    val = rb_String(val);
    printf("%*s`%s` ==> type(%d) `%*s`\n", indent, "", str, type,
    RSTRING(val)->len, RSTRING(val)->ptr);
    }
    #endif

    if (indent == 0) {
    printf("\n");
    }
    }


    // Returns output of command as a string
    //
    // see rb_f_backquote() in io.c
    //
    // needs to set exit code of command into rb_last_status
    //
    static VALUE m_backquote(VALUE self, VALUE commandVal)
    {
    VALUE arr = Qnil;
    char* commandStr = StringValueCStr(commandVal);

    if (commandStr) {

    printf("Executing backquote command on `%s`\n", commandStr);

    // This should be the captured output of the command.
    // I'll just reverse the string as the command value, here.
    //
    size_t len = strlen(commandStr);
    std::string ss(len, ' ');
    for (size_t i = 0, j = len - 1; i < len; ++i, --j) {
    ss = commandStr[j];
    }

    arr = rb_str_new2(ss.c_str());
    }
    else {
    printf("Error: cannot execute object\n");
    }

    return arr;
    }


    // Executes _cmd_ in a subshell, returning true (Qtrue) if the command
    // was found and ran successfully, false (Qfalse) otherwise.
    //
    // passed in elements may be arrays - may want to flatten and then
    // join with " "s between.
    //
    // See rb_f_system() in process.c
    //
    // needs to set exit code of command into rb_last_status
    //
    static VALUE m_system(int argc, VALUE *argv)
    {
    printf("Called Kernel#system on:\n");

    for (int i = 0; i < argc; ++i) {
    VALUE s = rb_String(argv);
    printf(" %2d. `%*s`\n", i, RSTRING(s)->len, RSTRING(s)->ptr);
    }

    return Qtrue;
    }

    // Might want to have separate functions for stdout and stderr, so they
    // can be separated...
    //
    static VALUE m_write_stdout(VALUE self, VALUE input)
    {
    if (TYPE(input) == T_STRING) {
    printf("We have captured (stdout): \"%*s\"\n",
    RSTRING(input)->len, RSTRING(input)->ptr);
    // Return the number of bytes written
    return
    rb_fix_new(RSTRING(input)->len*sizeof(RSTRING(input)->ptr[0]));
    }
    else {
    printf("Error: cannot write object to stdout\n");
    return Qnil;
    }
    }
    static VALUE m_write_stderr(VALUE self, VALUE input)
    {
    // Need to use rb_string_value if it can contain embedded nuls.
    char * got = StringValueCStr(input);
    printf("We have captured (stderr): \"%s\"\n", got);
    // Return the number of bytes written
    return rb_fix_new(strlen(got)*sizeof(got[0]));
    }


    int _tmain(int argc, _TCHAR* argv[])
    {
    NtInitialize(&argc, &argv);

    ruby_init();
    ruby_script("embedded");

    rb_define_global_function("`", RUBY_METHOD_FUNC(m_backquote), 1);
    rb_define_global_function("system", RUBY_METHOD_FUNC(m_system),
    -1);

    rb_define_singleton_method(rb_stdout, "write",
    RUBY_METHOD_FUNC(m_write_stdout), 1);
    rb_define_singleton_method(rb_stderr, "write",
    RUBY_METHOD_FUNC(m_write_stderr), 1);

    char* eval_strings[] = {
    "3",
    "nil",
    "true",
    "false",
    "5+6",
    "?c",
    ":fred",
    "'hello'",
    "\"hello\"",
    "'hello there'",
    "'123'*3",
    "3.8",
    "x = 123_456",
    "x * x",
    "\"#{x * x}\"",
    "111_111_111**2",
    "-111_111_111**3",
    "[1, 'two', 3.0]",
    "[[1,2,3],[4,5,6],[7,8,9]]",
    "/r[iou]se/",
    "`dir c:\\\\windows`",
    "h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' =>
    'asinine' } ",
    "h.length",
    "h['dog']",
    "h['cow'] = 'bovine' ",
    "h[12] = 'dodecine' ",
    "h['cat'] = 99 ",
    "h",
    "puts 'this is a test'",
    "$stderr.puts 'writing to stderr'",
    "system('TITLE', '4NT/Ruby')",
    "system('DELAY 3 & TITLE Changed window title from Ruby')",
    "5",
    };

    const int eval_strings_len = sizeof(eval_strings) /
    sizeof(eval_strings[0]);

    int status = 0;

    for (int i = 0; i < eval_strings_len; ++i) {
    status = rb_eval_string(eval_strings);
    print_ruby_value(status, 0, eval_strings);
    }

    ruby_cleanup(0);

    return 0;
    }
    Timothy Byrd, Aug 3, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Colin Paul Gloster
    Replies:
    48
    Views:
    1,842
    Colin Paul Gloster
    Apr 10, 2007
  2. Thomas Dodds

    Databind an embedded control in an embedded datagrid

    Thomas Dodds, Jul 26, 2004, in forum: ASP .Net Datagrid Control
    Replies:
    0
    Views:
    382
    Thomas Dodds
    Jul 26, 2004
  3. Photon 2038

    Embedded ruby question

    Photon 2038, Aug 23, 2006, in forum: Ruby
    Replies:
    0
    Views:
    101
    Photon 2038
    Aug 23, 2006
  4. Trans
    Replies:
    11
    Views:
    281
    micathom
    Sep 5, 2007
  5. Num GG
    Replies:
    2
    Views:
    342
    Num GG
    Nov 17, 2008
Loading...

Share This Page