[wxruby-users] embedding wxruby?

Alex Fenton alex at pressure.to
Mon Sep 15 06:50:27 EDT 2008


Hi Niklas

Niklas Baumstark wrote:
> as announced, I played a bit around with swig and now seem to have found a first solution for my embedded ruby GUI plugin system. So far, I managed to wrap a C++ wxWindow object into a ruby Wx::Window object. 
>   

Broadly, I think you should be able to use almost all of the existing 
wxRuby SWIG etc codebase in an embedded setting. The main things that 
will need to change are the library initialisation code (in swig/wx.i) 
and the Wx::App initialisation code (in swig/classes/App.i) .

You will in some way need to link the wx C++ App object to a ruby 
instance and make it a constant (like Wx::THE_APP in wxRuby). Having the 
App as a constant is the link that wxRuby uses to protect long-lived C++ 
objects like Windows from Ruby's garbage collection (see mark_wxApp).

> ===== SAMPLE START =====
....

>   * it is limited to be used with a wxWindow / Wx::Window and not at all generic.
>   

Take a look at the function wxRuby_WrapWxObjectInRuby in swig/wx.i - 
this does exactly what you want. It uses wxWidgets type-information 
system to wrap a C++ object in the correct ruby class.

It is applied to (almost) all methods in wxWidgets that return wxWindow* 
by a typemap.

>   * the ruby script doesn't know about wxRuby. It just gets the raw 
>     Wx::Window object. it can't use $window.name instead of 
>     $window.get_name, for instance, and it can't access it's non-trivial 
>     members, because the corresponding types are not initialized. 
>     i didn't figure out a way to setup the whole wxRuby namespace in one rush
>     (i would have to call every single Init_XY).

SWIG's support for multi-module libraries is weak so wxRuby has to work 
around this by massaging the default generated code.

The rake build system (in rake/rakewx.rb) appends a function called 
InitializeOtherModules to the generated file src/wx.cpp that initialises 
all the other modules, in alphabetic order. This is then called in 
Init_wxruby (in swig/wx.i).

The other important thing is that each class should not be initialised 
before its parent class. The script swig/fixmodule.rb adds a line to 
each generated cpp file that calls Init_wx[PARENTCLASS] before 
proceeding with initialising self.

>     the wx.rb could probably be included via rb_eval_string or something 
>     similiar for the sugar functionalities. didn't try it yet, however.
>   
The ruby API function you want is rb_require. Some of the things in the 
ruby code are not just "sugar" but needed to make the classes work 
properly - eg GC helpers.

>   * less important: the wxruby2.so has a size of 40MB. is it statically
>     linked against wxWidgets? If so, can this easily be turned off?

You could try strip -x to reduce the size. But SWIG adds a lot of 
overhead - the same runtime code is repeated and compiled for each SWIG 
class. I estimate that just getting round that would reduce the library 
size by about a third.

On Linux and OS X at least - haven't tried with Windows - you can have a 
wxRuby that is dynamically linked. If you have a dynamic build 
available, either have wx-config point to it by default, or pass 
WXRUBY_DYNAMIC=1 as an environment variable to rake.

Happy to help further but may be better to follow-up on the wxruby-dev 
list as this is fairly technical....

cheers
alex



More information about the wxruby-users mailing list