Documentation

Davyd, the GTK+ Perl bindings come with documentation in the perldoc format (which works upon man); each object has its unique perldoc page, so if you need to know all the methods of the Gtk2::TreeView widget, all you have to do is open a terminal and type:


$ perldoc Gtk2::TreeView

And you’ll be greeted by a screenful like this:

TREEVIEW(1)         User Contributed Perl Documentation        TREEVIEW(1)

NAME
       Gtk2::TreeView

HIERARCHY
         Glib::Object
         +----Glib::InitiallyUnowned
              +----Gtk2::Object
                   +----Gtk2::Widget
                        +----Gtk2::Container
                             +----Gtk2::TreeView

INTERFACES
         Glib::Object::_Unregistered::AtkImplementorIface

METHODS
       widget = Gtk2::TreeView->new ($model=undef)

           * $model (Gtk2::TreeModel)
...

Support of man pages, by the way, is sorely missed inside GTK+ itself: instead, you’ll have to use devhelp or point your browser to a long URI; I love devhelp, but I’m usually coding (with) development releases of many libraries, all installed inside a jhbuild sandbox so in order to make it find the autogenerated API documentation you’ll have to build devhelp inside the sandbox too – which is unnecessary pain I’d like to avoid inflicting upon myself.

Anyway, perldoc to the rescue: at the end of the object page you’ll find the SIGNALS section – if the object’s class exports signals, that is – which looks like this:

SIGNALS
       set-scroll-adjustments (Gtk2::TreeView, Gtk2::Adjustment, Gtk2::Adjustment)
       row-activated (Gtk2::TreeView, Gtk2::TreePath, Gtk2::TreeViewColumn)
       boolean = test-expand-row (Gtk2::TreeView, Gtk2::TreeIter, Gtk2::TreePath)
       boolean = test-collapse-row (Gtk2::TreeView, Gtk2::TreeIter, Gtk2::TreePath)
       row-expanded (Gtk2::TreeView, Gtk2::TreeIter, Gtk2::TreePath)
       row-collapsed (Gtk2::TreeView, Gtk2::TreeIter, Gtk2::TreePath)
...

As you can see, you have the signal name, the arguments of the callback and the eventual return value. The “gotcha” is that there are no named arguments, so you’ll have to know the C counterpart of the signal; this might be a worthy addition to the API documentation generation module.

Another dirty trick is to use the Data::Dumper module inside a callback you don’t know which arguments passes:


sub my_unknown_callback {
    use Data::Dumper;

    print STDERR Dumper(@_);
}

Which will print whatever the callback gives you – even descending into hashes and arrays if it knows how to print their contents.

If you don’t want to use a terminal and the perldoc command, there’s the Gtk2::Ex::PodViewer widget on CPAN, which comes with a podviewer application which you can use to browse the entire Perl documentation available on the system,or you can download PodBrowser which does a bazillion things more.

2 Replies to “Documentation”

  1. Yes. I’ve been using this documentation. I didn’t make it clear what callbacks I was referring to. I’ve noticed the signals are indeed documented. The callbacks I’ve had problems with are for things like GLib::IO::add_watch (why is the documented in GLib::MainLoop?) and the one to set sort functions for Treeviews. The C API talks about closures and lots of things that I know won’t exist in the Perl API. I didn’t know about the Data::Dumper trick.

    The documentation can be read in conjunction with the C documentation, but requires a little bit of skill to translate between languages (it helps if you can think of languages abstractly). I also have the advantage of being able to read through a list of functions wondering which one I want and suddenly remember once I read its name, because I know the API.

    For the person I’m teaching, I expect a lot of this looks like black magic, because they’ve not had a lot of exposure to the C API, and it’s all a bit confusing for them. There is a lot of, “you want to pass such-n-such” “how do you know that?” “its documented” “no it isn’t” “oh, I’m sure it is somewhere”.

    For me, this harks back to needing to develop a way to build language agnostic documentation, almost where you can simply provide a “translation” (if you will) for parts of the API that function differently, as well as new examples, &c. Then have the whole thing appear in Devhelp. I think I mentioned this at GUADEC, I’m just not entirely sure how you would implement it.

  2. The manpages are generated by a homebrew bit of code that pulls information from three sources: parsing of the bindings’ sources for call signatures, a special dialect of POD embedded in the bindings’ sources which can annotate those methods, and reflection on the bound library after compiling. That is, the method signature comes from scanning the sources (with hand-done fixups), the method description is written by hand, and the listings of enumeration values, object hierarchies, object properties, and signals all come from querying the GLib type system.

    The upshot is that until the signal handlers’ argument names are listed in the C library metadata, all we’ll get is types. The types are needed for marshalling, the names, er, aren’t strictly needed. Without metadata support in the upstream library, the names would have to come from hand-written annotations, which doesn’t work well in the long run (for a binding).

    For generic callbacks, such as the GSourceFunc, the binding uses hand-coded glue. The C libraries don’t include type information for these callbacks, so there’s nothing to query. It’s conceivable that we could take another approach to how the glue is done that would make it possible to scan the sources and possibly even reduce the amount of hand-written glue (think typemaps for coderefs, mmmm)… but with the impending arrival of full-scale introspection in GLib, this sort of thing would be obsolete, so it never occurred to us to pursue it. *ahem*

    And, um, Glib::IO::add_watch() is documented in the Glib::MainLoop manpage because g_io_add_watch() is declared in gmainloop.h. Yes, it really is that ad hoc. :-/ GLib’s API is not as cleanly object-oriented as GTK+’s so deciding how to arrange the docs is not easy. No matter where you put it, somebody complains “i never would’ve thought to look there.” Also, if we broke Glib::MainLoop into the various manpages dictated by the package names it documents, we’d have a bunch of one-function manpages, which, at the time it was all created, seemed like a bad idea.

    Finally, Davyd, as for translating between the perl and C APIs, have you see the Gtk2::api manpage? :-)

Comments are closed.