[Kde-bindings] Understanding QtRuby

Richard Dale rdale at foton.es
Tue Apr 8 10:16:02 UTC 2008

On Monday 07 April 2008 22:40:14 Jonathan Gardner wrote:
> I am no pro at Ruby. I do understand Python really well, including it's
> C interface.
> I am attempting to build a package in Lisp that will allow me to connect
> with Qt, possibly using the Smoke library. So I am poking at the QtRuby
> code to get started.
> However, I am completely befuddled by the most basic of statements. I am
> sure that a few pointers to the documentation would help me get on the
> right path.
> Consider the example shown at
> http://developer.kde.org/language-bindings/ruby/index.html
>       #!/usr/bin/ruby -w
>       require 'Qt'
> I believe that "require 'Qt'" loads the Qt.rb file, which simply loads the
> qtruby.qt file.
Yes, the require Qt statement loads qtruby4.so, which in turn loads 

>       a = Qt::Application.new(ARGV)
> This, I believe, is a simply constructor for the Qt::Application defined at
> line 182 in qtruby.rb. There is no C magic yet.
Yes, it is a constructor, but there has actually already been a lot of C 

>       hello = Qt::PushButton.new("Hello World!", nil)
> The PushButton class doesn't exist in qtruby.qt. I can't tell how this is
> getting dispatched.
The QtRuby classes are created dynamically at runtime. At the end of the 
Qt.cpp source there is a call to the ruby method init_all_classes in 
qtruby4.rb, which in turn calls another method init_class() in qtruby4.rb. 
That method calls create_qt_class() or create_qobject_class() which actually 
create the Ruby classes under Qt::Base.

>       hello.resize(100, 30)
> Pending an understanding of what PushButton is.
>       a.mainWidget = hello
> I can't tell how the mainWidget assignment is dispatched either.
Method calls in ruby can look like assignments, and this is a call to 
the 'mainWidget=()' method. It is changed at runtime to 'setMainWidget()' 
that is the name of the actual C++ method that is called.

>       hello.show()
>       a.exec()
> I believe the exec method here is defined at line 183.
>                 def exec
>                         method_missing(:exec)
>                         self.dispose
>                         Qt::Internal.application_terminated = true
>                 end
> I am not sure what this is doing. What is method_missing? where is dispose
> defined?
Ruby classes are open and so this isn't the complete definition of 
Qt::Application, it is just adding the exec() method to it. Normally the Ruby 
method_missing() call is used to trap method calls (see do_method_missing() 
in Qt.cpp), but here exec needs to be special cased. 

'method_missing(:exec)' is explicitely despatching the :exec message to 
method_missing() on the Qt::Application instance, whereas it normally would 
happen because Qt::Application didn't actually have a method of that name.

> Although I can find the Qt::Internal module, I don't see how
> application_terminated is defined.
It's a C function in Qt.cpp called set_application_terminated(). It is mapped 
onto the Ruby method 'application_terminated=()' in Qt.cpp like this:

rb_define_module_function(qt_internal_module, "application_terminated=", 
(VALUE (*) (...)) set_application_terminated, 1);

> I am sorry for being such a newbie when it comes to Ruby, but I think if I
> can get a few pointers I can get underway.
Yes, just keep doing a Q and A, and I can gradually explain how it works. The 
first thing to understand though is how method_missing() is working in the 
binding, and how you might do the same thing in lisp. Try this code:

class TestMethodMissing
    def method_missing(symbol, *args)
        puts "attempting to call a missing method: #{symbol} in 

        if args.length > 0
          puts "first argument: #{args[0]}"

        if args.length > 1
          puts "second argument: #{args[1]}"

t = TestMethodMissing.new
t.baz("hello", "ruby")

-- Richard

More information about the Kde-bindings mailing list