Embedding Ruby as plugin

T

Tobias Grimm

Hi!

I have an application written in C++, that provides a plugin interface. What I
would like to do now, is to implement a plugin, that allows to execute a ruby
script, like this:

1) Application loads plugin.so
2) Application invokes plugin
3) Plugin creates object "interface" of class Interface
4) Plugin loads rubyscript.rb
5) rubyscript.rb uses interface object created in 3) to send messages to the plugin

I used SWIG to create a wrapper for the Interface class that the ruby script
should use. If I simply wanted to create an ruby extension, the wrapper should
just be compiled to a lib, that ruby can load with a require statement. But now
the wrapper is part of the plugin, which itself is loaded by the application.
How do I get the ruby script know about the Interface class and the interface
object to use?

Tobias
 
J

Joel VanderWerf

Tobias said:
Hi!

I have an application written in C++, that provides a plugin interface.
What I would like to do now, is to implement a plugin, that allows to
execute a ruby script, like this:

1) Application loads plugin.so
2) Application invokes plugin
3) Plugin creates object "interface" of class Interface
4) Plugin loads rubyscript.rb
5) rubyscript.rb uses interface object created in 3) to send messages to
the plugin

I used SWIG to create a wrapper for the Interface class that the ruby
script should use. If I simply wanted to create an ruby extension, the
wrapper should just be compiled to a lib, that ruby can load with a
require statement. But now the wrapper is part of the plugin, which
itself is loaded by the application. How do I get the ruby script know
about the Interface class and the interface object to use?

Not sure I understand. Where is the ruby interpreter in this picture?
Your C++ app embeds it? Or plugin.so embeds it?

What if you just set a global variable, $interface, before loading
rubyscript.rb, which references this global?

Is the problem then that you don't want to use a global, for the usual
good reasons?
 
T

Tobias Grimm

Joel said:
Not sure I understand. Where is the ruby interpreter in this picture?
Your C++ app embeds it? Or plugin.so embeds it?

plugin.so embeds it. I can't change the C++ app, it will never know, that one of
it's plugins uses ruby.
What if you just set a global variable, $interface, before loading
rubyscript.rb, which references this global?

Is the problem then that you don't want to use a global, for the usual
good reasons?

No... I could live with some globals. Althought I would probably use a static
factory method to return an Interface instance.

My problem is, that I don't know how to make my C++ classes, which are linked to
plugin.so, available to ruby which is embedded by plugin.so.

A usal ruby extension would just load the extension from a lib. But in my case
the lib containing the extension itself is running the ruby script

Lets say, I have interface.h which defines a C++ class "Interface" with a static
methode that returns a singleton instance of this class. It may get the instance
from a global variable.
SWIG now creates an interface_wrap.c, which I compile and link to my plugin.so.
Within the plugin.so some methode should now run the ruby script, calling
ruby_init and all the stuff to handle exceptions and so on.
But how do I let the ruby script know, that there is a class "Interface"? A
simple 'require "interface"' doesn't work.

Tobias
 
R

Richard Dale

Tobias said:
Hi!

I have an application written in C++, that provides a plugin interface.
What I would like to do now, is to implement a plugin, that allows to
execute a ruby script, like this:

1) Application loads plugin.so
2) Application invokes plugin
3) Plugin creates object "interface" of class Interface
4) Plugin loads rubyscript.rb
5) rubyscript.rb uses interface object created in 3) to send messages to
the plugin

I used SWIG to create a wrapper for the Interface class that the ruby
script should use. If I simply wanted to create an ruby extension, the
wrapper should just be compiled to a lib, that ruby can load with a
require statement. But now the wrapper is part of the plugin, which itself
is loaded by the application. How do I get the ruby script know about the
Interface class and the interface object to use?
I'm not familiar with the code generated by SWIG, but you can start ruby and
define a class from C like this:

ruby_init();
ruby_run();

interface_module = rb_define_module("Interface");
interface_class = rb_define_class_under(interface_module, "Interface",
rb_cObject);

# I assume Swig generates various wrapper methods like this:
rb_define_method(interface_class, "foobar", foo_bar, 1);
...


rb_require("rubyscript.rb");

# Call an initialization method to create the "interface" instance
rb_funcall(interface_class, rb_intern("init_rubyscript"), 0);

-- Richard
 
T

Tobias Grimm

Richard said:
# Call an initialization method to create the "interface" instance
rb_funcall(interface_class, rb_intern("init_rubyscript"), 0);

You're totally right. I missed calling the init function generated by SWIG. It's
called Init_modulename(void). Normally ruby invokes this init function
automatically, when loading an extension. But in my case, I've to do it myself.

Thanks a lot!

Tobias
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top