tags:

views:

562

answers:

1

I have embedded Ruby inside my C++ application. I have generated the bindings using SWIG.

Basically, I run the ruby file and then Ruby takes over and calls my C++ class.

Based on my previous question, I would like to get the current instance of the class that is defined in the ruby file back to the C++ class so that I may execute instance methods.

I execute the ruby file as follows:

rb_eval_string_protect(<ruby script string>, &status );

rb_funcall(Qnil, rb_intern("main"), 0);

The global main method in the script creates an instance of the defined class in the file. That's the instance I am after.

If I have to, I will add a parameter or another function to pass the instance back, however, I'm not sure how to define that in C++ so that when SWIG generates the binding, it all works ok.

Any help would be appreciated.

Previous Question: Calling Ruby class methods from C++

+1  A: 

The C api for ruby does its best to preserve ruby's functional nature, so rb_eval_string_protect() returns the VALUE of the last line of the script given, and rb_funcall() returns the VALUE of the last line of the method invoked.

So the trick is really to think of it as how would you get that instance value in pure ruby? If it's just the return value of main, like

# I'm a ruby script!
main_retval = main()

Then capturing the return value in C is similar:

// I'm some C (or C++) code
VALUE main_retval;
// ...
rb_eval_string_protect("...", &status);
main_retval = rb_funcall(Qnil, rb_intern("main"), 0);

And would give you a reference to the ruby object returned by main.

You can use this object as normal, calling methods and the like

VALUE main_retval_as_string = rb_funcall(main_retval, rb_intern("to_s"), 0);
rampion
That worked perfectly. Thank you.
Robert Rouse