Embedding 1.9

Folks:

I’m working on the “Extending Ruby” chapter (now an appendix) for the
third PickAxe, and I’m finding a whole bunch of conflicting
information. Reading the source, it seems like there’s no canonical
way of embedding Ruby in a C application. I have lots of alternatives
that seem to work, but I want to be more authoritative than that.

Does anyone have any pointers to stuff that would help?

Thanks

Dave

Have you checked out VIM? It has ruby embedded and provides an interface
into vim buffers from ruby. HTH. Good luck.
–mark


blog: http://hasno.info

On Jan 7, 2008, at 7:41 PM, Mark G. wrote:

Have you checked out VIM? It has ruby embedded and provides an
interface into vim buffers from ruby. HTH. Good luck.

Mark:

I don;t believe it has Ruby 1.9, though.

Dave

Hi,

In message “Re: Embedding 1.9”
on Tue, 8 Jan 2008 06:44:08 +0900, Dave T. [email protected]
writes:

|Folks:
|
|I’m working on the “Extending Ruby” chapter (now an appendix) for the
|third PickAxe, and I’m finding a whole bunch of conflicting
|information. Reading the source, it seems like there’s no canonical
|way of embedding Ruby in a C application. I have lots of alternatives
|that seem to work, but I want to be more authoritative than that.
|
|Does anyone have any pointers to stuff that would help?

Perhaps “authoritative” means “information from the original author”
but I don’t remember I wrote such document (sigh).

Basically, you have to call:

ruby_sysinit() for command line argument initialization (optional)
RUBY_INIT_STACK() for GC stack initialization
ruby_init() for ruby interpreter initialization

and wrap ruby calls with rb_protect() for initialize exception frame.
You can load Ruby programs with rb_load(). You can call ruby programs
from string via rb_eval_string().

          matz.

Hi,

In message “Re: Embedding 1.9”
on Tue, 8 Jan 2008 13:22:01 +0900, Dave T. [email protected]
writes:

|In 1.9, do we also now need to call set_locale()?

Do you mean setlocale()? It’s optional. If you call it,
Encoding.default_external will be set according to your locale,
otherwise it will be ASCII-8BIT.

          matz.

Moved over from ruby-talk…

On Jan 7, 2008, at 9:36 PM, Yukihiro M. wrote:

You can load Ruby programs with rb_load().

In 1.9, though, is that enough, or do we then have to call rb_iseq_new/
eval to have the file’s contents actually run (when I try just
rb_load_file, it gets compiled but the code in the file doesn’t appear
to be actually executed).

From an embedding point of view, this is slightly problematic, as
rb_load_file returns VOID *, so it’s hard to pass the parse tree on.

Should I perhaps be calling rb_load(rb_str_new2(“file.rb”, 0)?

Dave

On Jan 7, 2008, at 9:36 PM, Yukihiro M. wrote:

and wrap ruby calls with rb_protect() for initialize exception frame.
You can load Ruby programs with rb_load(). You can call ruby programs
from string via rb_eval_string().

In 1.9, do we also now need to call set_locale()?

Dave

Dave T. wrote:

Dave

Quite true. My addled eyes missed the blatant 1.9 in the title.

It did get me started on applying a little elbow work to them problem.
The vim code ports to 1.9 just fine. Changing a few of those pesky
RSTRING(xyz)->ptr and len’s to their new macros eliminates the majority
of the compile errors. The only other item seems to be error info
handling, which went from being a static variable to a function
rb_errinfo. I’m sure you’ve already run into all the nitty gritty. I’ve
attached a patch versus the current
vim trunk. I haven’t tried anything more intensive than loading and
executing a simple file as of yet.

–mark

On Jan 7, 2008, at 11:38 PM, Dave T. wrote:

From an embedding point of view, this is slightly problematic, as
rb_load_file returns VOID *, so it’s hard to pass the parse tree on.

Should I perhaps be calling rb_load(rb_str_new2(“file.rb”, 0)?

Also, ruby_init_gems(opt) is a static method in ruby.c, and so can’t
be called from code that embeds Ruby (it could be called via
process_options(), but that really does too much). A solution might be
to change the calling sequence to

void
ruby_init_gems(disable_gems)
{
VALUE gem;
gem = rb_define_module(“Gem”);
rb_const_set(gem, rb_intern(“Enable”), disable_gems);
Init_prelude();
}

and change the call to

ruby_init_gems(opt->disable_gems ? Qfalse : Qtrue);

Dave

On 08/01/2008, Yukihiro M. [email protected] wrote:

However, calling setlocale should not break ruby 1.9 since the
interpreter does it as well :wink:

Thanks

Michal

On Jan 8, 2008, at 12:20 AM, Mark G. wrote:

case TAG_RAISE:
case TAG_FATAL:

Mark:

Are you manually defining the TAG_xxx values somewhere? eval_intern.h
isn’t installed onto the user side on my box.

Dave

Dave T. wrote:

appear to be actually executed).

From an embedding point of view, this is slightly problematic, as
rb_load_file returns VOID *, so it’s hard to pass the parse tree on.

Should I perhaps be calling rb_load(rb_str_new2(“file.rb”, 0)?

Dave,

I had to do the following to get it working:

/*

  • Forward declarations for Ruby
    */
    void *
    rb_compile_cstr(const char *f, const char *s, int len, int line);

int main()
{
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
ruby_script("…");
ruby_run_node(rb_compile_cstr(“yourfile”,
(const char*)“p :hello”,
/* strlen / 8, / line no */ 1));

}

I also had to change some things in YAML/syck when I tried to link
everything statically… but then no .so files work anymore.

Regards,

Michael

On Jan 8, 2008, at 1:59 AM, Michal S. wrote:

However, calling setlocale should not break ruby 1.9 since the
interpreter does it as well :wink:

Right. The interpreter calls a bunch of methods during initialization.
I’m trying to determine the minimum subset required for safe 1.9
operation. I think I’ve got it now, and I’ll be pushing it as part
of the beta in the next few days.

Thanks

Dave

<(08/01/08 16:08) Dave T.>

Are you manually defining the TAG_xxx values somewhere? eval_intern.h isn’t
installed onto the user side on my box.

Dave,
Those are defined locally in if_ruby.c, that seems to be the convention
as the tcltk extension does the same. I wonder if those should be pushed
into ruby.h to ease embedding…?
–mark

On Jan 8, 2008, at 10:34 AM, Michael N. wrote:

I had to do the following to get it working:

Michael:

For my very basic example, I went with:

int main(int argc, char **argv) {
VALUE result;

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();

rb_require(“sum.rb”);
rb_eval_string("$summer = Summer.new");
rb_eval_string("$result = $summer.sum(10)");
result = rb_gv_get(“result”);
printf(“Result = %d\n”, NUM2INT(result));
ruby_finalize();
exit(0);
}

It worries me that there are so many ways of doing this, and so many
init methods that may or may not be needed. It also worries me that
this doesn’t set up the gem environment.

Dave

On Jan 8, 2008, at 11:27 AM, Hugh S. wrote:

rb_require(“sum.rb”);

WRT Michael’s " but then no .so files work anymore." – do you need
the ‘.rb’ in there for that to work?

No, it works fine with rb_require (but not, I believe, with rb_load).

Dave

On Wed, 9 Jan 2008, Dave T. wrote:

int main(int argc, char **argv) {
VALUE result;

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();

rb_require(“sum.rb”);

WRT Michael’s " but then no .so files work anymore." – do you need
the ‘.rb’ in there for that to work?

    [...]

ruby_finalize();
exit(0);
}

It worries me that there are so many ways of doing this, and so many init
methods that may or may not be needed. It also worries me that this doesn’t

I thought that: “What I tell you three times is true” ? :slight_smile:

set up the gem environment.

Dave

    Hugh, who's just following along, not got into 1.9 yet really.

On Wed, 9 Jan 2008, Dave T. wrote:

On Jan 8, 2008, at 11:27 AM, Hugh S. wrote:

WRT Michael’s " but then no .so files work anymore." – do you need
the ‘.rb’ in there for that to work?

No, it works fine with rb_require (but not, I believe, with rb_load).

Thanks.

Dave
Hugh

On Jan 8, 2008, at 11:05 AM, Mark G. wrote:

Are you manually defining the TAG_xxx values somewhere?
eval_intern.h isn’t
installed onto the user side on my box.

Dave,
Those are defined locally in if_ruby.c, that seems to be the
convention
as the tcltk extension does the same. I wonder if those should be
pushed
into ruby.h to ease embedding…?

That’d get my vote. I’ve copied core on this…

Dave

On Jan 8, 2008, at 3:35 PM, Paul B. wrote:

Your example should catch exceptions:

Agreed: the second version in the book does, but for this one I wanted
to just show the principle. But I didn’t know about ruby_cleanup,
which is neat. Thanks.

Dave