# Embedded Ruby Question

**URL:** <https://www.ruby-forum.com/t/embedded-ruby-question/100944>\
**Category:** Ruby\
**Created:** [August 2, 2006, 1:57am UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944 "2006-08-02T01:57:36Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 2, 2006, 1:57am UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/1 "2006-08-02T01:57:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 2, 2006, 2:51am UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/2 "2006-08-02T02:51:38Z")

</div>

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).

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 2, 2006, 3:30am UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/3 "2006-08-02T03:30:14Z")

</div>

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  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 3, 2006, 12:00pm UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/4 "2006-08-03T12:00:10Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 3, 2006, 12:00pm UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/5 "2006-08-03T12:00:22Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 3, 2006, 12:01pm UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/6 "2006-08-03T12:01:48Z")

</div>

Logan,

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

-Brian

* * *

Brian E Campbell  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 3, 2006, 12:01pm UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/7 "2006-08-03T12:01:20Z")

</div>

On Aug 1, 2006, at 9:28 PM, Brian Campbell wrote:

> 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 P.s 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.

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 3, 2006, 12:08pm UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/8 "2006-08-03T12:08:39Z")

</div>

Hi,

At Wed, 2 Aug 2006 12:55:46 +0900,  
Logan C. 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.

---

<div class="post-metadata">

**Author:** ![Brian\_Campbell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/fbc32d/32.png) [@Brian\_Campbell](https://www.ruby-forum.com/u/Brian_Campbell)\
**Post date:** [August 3, 2006, 2:23pm UTC](https://www.ruby-forum.com/t/embedded-ruby-question/100944/9 "2006-08-03T14:23:26Z")

</div>

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

#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[i], 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[i] = 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[i]);
    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[i]);
    print_ruby_value(status, 0, eval_strings[i]);
}

ruby_cleanup(0);

return 0;

```

}
