wxruby-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Wxruby-dev] Re: SWIG Question


From: Lyle Johnson
Subject: [Wxruby-dev] Re: SWIG Question
Date: Wed, 11 Sep 2002 20:57:46 -0500
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020607

Curt Hibbs wrote:

I looked at what the Python people did with SWIG to produce wxPython, and I
looked at what you did to produce FXRuby, and this have left me with a
nagging question: is it really necessary to duplicate the all of the
underlying library's constants and such in the interface files when SWIG is
supposed to be able to process C/C++ header files and figure that stuff out
itself?

It is possible that, with the latest versions of SWIG, this may no longer be necessary. You need to know that, for example, wxPython was developed using SWIG 1.1, which didn't include a preprocessor and a number of other advanced features that SWIG 1.3 has. Similarly, when I began development of FXRuby (using a very early SWIG 1.3 release) it was missing a lot of the functionality that is currently available. One such feature that immediately comes to mind is the recently added support for overloaded methods; in earlier versions of FXRuby, I was having to "roll my own" version of overloading to make it work. When Dave (Beazley) got overloading working for SWIG 1.3.14, I was able to remove a lot of that cruft from FXRuby.

Duplicating the header file definitions in the interface files seems like a
potential maintenance headache. Every time the underlying library changes,
you'd have to do a diff to see what changed and then manually make those
changes in the interface files.

Agreed, this is a maintenance problem, so you should avoid it when possible.

My ideal would be to not have to create any interface files at all. Instead,
I would like to have SWIG process the library's header files to create a
"raw" ruby binding to the library. And then, on top of that, create a layer
of Ruby code that presents a more Rubyesque api to the outside world.

I have used a similar approach for other libraries, and it works quite well. In fact, though most of FXRuby is implemented in the extension module's shared library, some of the code is implemented in Ruby. My Ruby interface to CLIPS took this approach as well, wrapping the low-level C functions and then building an object-oriented interface in Ruby that calls those functions under the hood.

But the fact that both wxPython and FXRuby have created extensive interface
files tells me that I must be missing something -- that there is something
important that I don't know.

There are some things that SWIG still doesn't do (and, to be fair, perhaps can't do in an automated way).

For example, one of my requirements for FXRuby is that you should be able to derive new Ruby classes from the (wrapped) FOX classes and override their virtual functions, and everything "just works". Let's say you want to implement a new layout manager for FOX, and you decide to subclass FXCompsite to get started:

   class MyLayoutManager < FXComposite
   end

Since some of the key functions involved in layout are the C++ virtual functions layout(), getDefaultWidth() and getDefaultHeight(), you'll probably need to override them to do the right thing for your layout manager:

   class MyLayoutManager < FXComposite
       def layout
           # Lay out my child widgets
       end
       def getDefaultWidth
           # Return the default width for this window
       end
       def getDefaultHeight
           # Return the default height for this window
       end
   end

Unfortunately, it's not that simple. You can create an instance of MyLayoutManager and use it, all right, but underneath it's still just an FXComposite as far as FOX is concerned. Why? Because there's no C++ inheritance involved. That is to say, when some object calls the object's virtual getDefaultWidth() function in C++-land, it's going to stop when it reaches FXComposite::getDefaultWidth(). The painful reality is that, for this virtual function dispatch to work, you must derive new C++ classes for any C++ class that has virtual functions that you want to override. I'll stop here for now, but there's a lot more to say about the topic ;)

Another issue is interaction with Ruby's garbage collector. As you may know, Ruby uses a "mark and sweep" GC algorithm that extension writers must pay attention to. If one of your Ruby objects holds references to other objects, you need to provide a function that "marks" those objects as reachable so the garbage collector won't clobber them prematurely. This, again, is not something that can be determined automatically by SWIG; you pretty much need to be familiar enough with the library to know which function calls cause new references to be saved (or released).

So, my question is: is there some reason why the approach I outlined above
won't work?

Not necessarily. The approach you've outlined will work for a lot of cases, and it's the one I use when I have the option. I'm not familiar enough with wxWindows enough to know how much of a problem the issues I identified are going to affect your decision. But Robin Dunn (the original developer of wxPython) is a pretty sharp guy, and I suspect that to get the full wxWindows "experience" you may have to make a similar investment.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]