Re: gtk2 news



On man, 2002-09-09 at 18:43, Scott Smith wrote:
I really would like to see this done, so I started on it last weekend.


Great news.
 
Here is a general overview of what I was thinking, and following that, 
what I've got so far.  Some of the overview is basic if you're into XS.
I'm not, yet, really.  It looks like everyone who has played with it
is roughly on the same page, though I haven't tried inline C yet.
I was shooting for XS.


There is really no difference between Inline::C and XS except for
automatic compilation.

* Libraries and header files:

The libraries used to compile C programs using Gtk2 are the ones
we want to wrap with Perl modules.  While certain binutils tools like nm
can tell us the names of functions in the library directly, we need,
I believe, the header files to get the exact prototype.

On systems with pkg-config installed, getting the list of both
libraries and header files for gtk2 is easy:

  pkg-config gtk+-2.0 --cflags --libs

The libraries include gtk, gdk, pango, atk, glib, and a few
others upon which gtk is dependent.

* After wrapping the libraries:

While basic wrappers for the libraries would be nice,
all we'd be left with is perl code like:

    use libgtk;
    my $winptr = libgtk::gtk_window_new();
    libgtk::gtk_window_set_title($winptr,"My Title");


This would be silly. 
XS will do all the wrapping for you.
You just give the XS compiler a couple of hints, and the methods will be
placed in the right packages.

The hints in this case would be:
MODULE = Gtk::Window    PACKAGE = Gtk::Window   PREFIX = gtk_window_

This makes gtk_window_new() become Gtk::Window->new() in Perl.

The previous wrappers constructed perl classes (packages)
for the various types available in Gtk, and made methods
in the packages which called the real c functions with 
shorter names.  Once the above perl code is possible to execute,
going to this next level should be simple.  All GtkWidget
objects are derived from GObject, and all GObjects have
a GType, for which there are functions in to get 
inheritance information.  In a dynamically typed language
like perl we could pre-build the packages as modules,
or build them on-the-fly at run-time.

As far as I can tell there is no way to introspect methods (please
correct me if I'm wrong - I'd like to be this case).

So while you could create the packages at runtime, the objects blessed
into them would be somewhat useless... As they could be used via
properties and signals only.

The methods which wrap the c-function-equivalents will have
to translate pointers returned from the c library into perl
objects of the correct type (the old version seemed to use
a hashref with a single key/value (_gtk => pointer_value).

Again XS will do this translation for you. This is what typemaps are
for.

Using a hashref is actually a pretty neat idea. If the plain C pointer
was used the object would be opaque to the Perl side of things. So
subclasses would have nowhere to put object private data (I do know
about set_data/get_data - but those present other problems).

This translation will involve construction of a new perl object
when a pointer value is first encountered, and lookup
of an existing perl object on subsequent encounters with the 
pointer.

They will of course also have to extract the c-pointer values from
the perl object ref when passing parameters into the method.

When the C library wants a function pointer:

As was pointed out previously on the list, getting perl to 
call C is a bit more straightforward than getting C to call 
perl back later, via a callback.  I'll get into this after 
the XS stuff below.

* SWIG and XS parsing the headers:

There are two tools typically used to bind C libraries to perl,
xs and swig.  swig is built to work from library header files to 
produce a perl wrapper.  With xs you code the c back-end for a
perl module in a special c/perl hybrid language, but there is a 
script called h2xs which automatically produces xs code for you
from C header files.  

Both h2xs and swig seem like they could do the trick, but both fail
when parsing the gtk header files.  Unfortunately, I can get neither 
of them work on the gtk headers.  h2xs doesn't let you give it
-I parameters to change the include path, but even after
modifying the script to search the gtk directories, the underlying
C::Scan module fails in some way when parsing the header.  Swig also
has issues.

So I wrote my own parser for the gtk-oriented header files.  If 
anyone wants to try to figure out why h2xs or swig do not work, 
and fix them, that would be great.  I was more confident I could
write a parser for the headers myself than I was that I could fix
someone else's, so I did that instead.


All the bindings I've looked at use .defs file for generating their
stubs. This is not a bad idea as header parsing (which is rather error
prone) and the following handcleaning of the results, can be done just
once.

* Where things are so-far for me:

I have as script complete which uses pkg-config, gets a list of the 
libraries used by gtk on the system.  I just finished it this morning,
and will try to get it on my web site tonight.

I run the header files used by gtk through the gcc preprocessor to get a
clean super-header, and then scan the super-header for prototypes
for every function in the library possible.  Many function do not
appear to have prototypes, and are possibly not part of the public API.

Each prototype is parsed and a multilevel hash is constructed to 
describe each function.  I just got the parser to not choke on a few
exotic functions last night.

* Here was my tentative plan for what to do next:

1. Extend the script to write the actual xs code for each function.

Such a script allready exists in the old binding.
Shouldn't need that many changes.


2. Test to make sure we can build the basic perl wrappers for the libs.
   (like Goran's code but without having to hand-write gtkperl_*
    wrappers)

3. Produce a module which will be directly "used" by the programmer.
   It should:
     . "use" the lib* modules.
     . query the GType system and build a perl inheritance tree.
     . each package generated should know its function prefix
     . AUTOLOAD should create class methods which are wrappers
       for underlyin c functions on the fly.

This is how the python binding do it - at least they did for gtk+ 1.
In Perl it doesn't make sense as XS will do it for you (better and
faster).

4. Ensure that the wrappers handle genral perl <-> c object      
   translation.  Creating a GClosure, or anything else with a C
   function pointer, out of aperl closure looked like it might take some
   work, but at first glance it looks like Goran's code is doing it.

A Perl closure seen from C is just a SV * (a CODE ref in Perl).
Arguments will need marshalling though...
 
5. Work on error handling, using the function prototype info
   to produce clear messages when wrong paramters are passed to
   the gtk wrapper.






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