README.guile-gtk 19.2 KB
Newer Older
1 2 3 4 5 6 7 8 9
README for guile-gtk preliminary version 0.17
*********************************************

This is some glue code to make Gtk accessible from Guile so it provides
a convenient interface for Scheme programmers to develop visual
applications. It can optionally integrate with GNOME via the Gnome-guile
module.

Guile-gtk was started by Marius Vollmer <mvo@zagadka.ping.de> and is
10
currently maintained by Ariel Rios<jarios@usa.net> and other intrepid Guile
11 12 13 14 15 16 17 18 19 20 21 22
hackers around the world.

Guile-gtk is free software licensed under the GPL.

New versions of this package will be available from

    http://www.ping.de/sites/zagadka/guile-gtk/
or in one of the mirrors:
    http://erin.netpedia.net/guile-gtk/       		(USA)
    http://erin.linuxbox.com/guile-gtk/       		(USA)
    http://linux.cem.itesm.mx/~jarios/guile-gtk/        (MEXICO)

23
You can also get at the most recent development sources through the Gnome
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
CVS repository.  Guile-gtk is contained in the gnome-guile module.
See www.gnome.org for details.

Guile-gtk was made with the idea of making it as generic as possible.
As a result, it should be easy to extend it to new widgets and other Gtk
extensions.

It might even be possible to use some of this code for wrapping
completely different C libraries, but that was not the goal.

To somewhat unify the different high-level language bindings (such as
the ones for Perl, Python, Objective C, maybe Java, etc.) Marius
Vollmer tried to collect the salient bits of the Gtk API into a formal
description.

You should be able to generate large parts of the language specific
glue code from it.  Unfortunately, this formal description hasn't
stabilized yet and we are currently more interested in completeness than
in generality.

   Table of Contents

   - Acknowledgements
   - Bugs
   - Mailing List
   - Gtk versions
   - Related stuff
   - Package contents   
   - Installing
   - Testing
   - Dynamic Linking
   - Wrapping Your Own Widgets      
   - Composite Types and `call-by-reference'
   - Documentation


Acknowledgements
----------------

Many people have contributed to guile-gtk by now.  Many thanks to all
of them!  Please refer to the ChangeLog for details.


Bugs
----

The main aim still is robustness, with an eye towards completeness.  It
should not be possible to crash your program from Scheme.  Guile-gtk
has to cope with anything.  So if you find that your program crashes
and you think it is due to a bug in your Scheme code, you have
actually found a bug in guile-gtk or Gtk.

Please report these bugs to the current maintainer,Ariel Rios,
<jarios@usa.net> or to the mailing list <guile-gtk@sourceware.cygnus.com>

Mailing List
------------
To subscribe to the list send mail to:
<guile-gtk-subscribe@sourceware.cygnus.com>

To post messages please write to:
<guile-gtk@sourceware.cygnus.com>

Gtk Versions
------------

[ Whoa, can anyone put this into more simple words?  Seems like I can't
  see the forest for all the trees. ]

There are two lines of Gtk versions in active development, modeled
after the Linux kernel scheme, I think.  One is the stable branch that
95
will maintain binary compatibility, and the other is the development
96 97
branch, where new features are tried out.  The stable branch has
version numbers like 1.2.x; the development branch is labeled 1.3.x
98
and the absolutely latest version is made available through CVS.
99 100 101

Guile-gtk can be built for both gtk-1.2 and gtk-1.3.  It is possible
to have these two versions of guile-gtk installed and in use
102
simultaneously, but the sources can only be configured for one of them
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
at any one time.  That is, when you want to switch between Gtk
versions, be sure to make distclean and re-configure.

The version number of gtk that guile-gtk has been built for will be
reflected in the names of the installed programs and libraries.  When
you are building for gtk-1.2, for example, you will get guile-gtk-1.2
and libguilegtk-1.2.

Likewise, the guile modules include the version of gtk in their
prefix.  The modules for gtk-1.2 are named `(gtk-1.2 <suffix>)', for
example.  When you want to use a specific version of gtk, you thus
just have to use the right module names.  You can't mix gtk-1.2 and
gtk-1.3 modules and you will receive an error when you try to do so.

This package will also install generic aliases for both the modules
and the guile-gtk programs that refer to the gtk version that has been
used while building it.  In addition to "guile-gtk-1.2" or
"guile-gtk-1.3" there will also be a symlink from plain "guile-gtk" to
one of them.  There will also be modules called `(gtk <suffix>)' that
will dispatch to the `appropriate' version of gtk.  What is
`appropriate' is determined in two steps: when one of the specific
modules has already been activated, the generic modules will just
refer to them.  When no specific gtk module has been used before, they
will refer to the version of gtk that has been used for building the
package.

Both guile-gtk-1.2 and guile-gtk-1.3 will activate their specific
versions of the gtk modules at startup.  Thus, the generic modules
`(gtk <suffix>)' always refer to gtk version used by the guile-gtk
executable used to run them.

Guile-gtk should always target the latest released versions of Gtk in
both lines of development.  There is no reason to use anything else
than the latest `bug-fixing' gtk-1.2, and everybody who is using the
unstable gtk-1.3 series can be expected to be up-to-date, right?


Related Stuff
-------------

Jeff Dike is writing a layer of macros/functions on top of guile-gtk
that makes it simpler and fairly uniform to create widgets within
Guile.  It is available here

     http://www.mv.com/ipusers/karaya/simple-gtk/simple-gtk.scm

David Lutterkort is writing a tool that makes it easy to give command
line programs with too many options a nice GUI.  Available here

     http://www.cs.purdue.edu/homes/lutterdc/software/wickel.html

There is also a list of applications developed using guile-gtk in:
     http://erin.netpedia.net/guile-gtk/apps.html

Package Contents
----------------

 guile-gtk.c
 guile-gtk.h     Support for converting between Scheme types and Gtk types
                 and the basic machine for making it all happen.

 gtk-support.c   Some handwritten glue code.
 guile-compat.c  Code to adapt to different versions of Guile.
 gtk-compat.c    Code to adapt to different versions of Gtk.

 gdk-1.2.defs    The formal description of the Gdk API for gtk-1.2.
 gtk-1.2.defs    The formal description of the Gtk API for gtk-1.2.

 gdk-1.3.defs    The formal description of the Gdk API for gtk-1.3.
 gtk-1.3.defs    The formal description of the Gtk API for gtk-1.3.
 
 build-guile-gtk A Scheme program to generate much of the glue code.

 gtk/gtk.scm     The Scheme part of the (gtk gtk) module.
 gtk/gdk.scm     The Scheme part of the (gtk gdk) module.
 gtk/dynlink.scm Alternative dlopening that works better than the
                 one in Guile.
 gtk/event-repl.scm 
                 Support for event driven read-eval-print loops.
 gtk-1.2/        Scheme modules for Gtk-1.2
 gtk-1.3/        Scheme modules for Gtk-1.3

 examples/       Some example programs.

The rest is the usual configuration and building cruft.


Installing
----------

See INSTALL for generic installation instructions.

This package will build a new program, "guile-gtk" that is a regular
Guile interpreter with the Gtk support already linked in.  It accepts
the usual "guile" command line options and in addition to that, it
also understands the Gtk options.

On a few systems, this package is also able to arrange things so that
you can just use the (gtk gtk) module from a vanilla "guile".  In
fact, "guile-gtk" is only a kludge until dynamic linking works well
enough.

The package will also install "build-guile-gtk", a program for
generating glue code for arbitrary *.defs files.  It can also produce
new executables that are variants of guile-gtk, with a different set
of glue code pre-linked.

NOTE: This package installs its Scheme code in a location determined
by the prefix given to the configure script.  It does not pay
attention to where your Guile is installed.  When Guile and this
package are installed under the same prefix, everything is fine.  When
you use a different prefix for this package, you need to make sure
that Guile knows about this location.  For example, when you install
this package under /usr/local/stuff/guile-gtk, you may want to add
GUILE_LOAD_PATH=/usr/local/stuff/guile-gtk/share/guile to your
environment.  Or you might want to make some symlinks.  This package
does not try to be clever about these issues, as there are too many
variations and potential solutions.

Testing
-------

    % cd examples/
    % ../guile-gtk -s test-gtk.scm

should pop up a familiar pile of buttons.  Not every test has been
implemented, tho.  All unexpected behaviour is probably a bug and I
would be glad if you would tell me about it.


Dynamic Linking
---------------

Guile-gtk uses its own approach to dynamic linking of compiled code
modules.  The experimental mechanism provided by Guile itself proved
to be troublesome in the real world.

As long as you build your shared libraries with libtool, and you have
the dlopen function, everything should just work.  At least in theory.
Please refer to gtk/dynlink.scm for the implementation and gtk/gdk.scm
for a simple application.

The code in gtk/dynlink.scm parses the *.la files installed by libtool
and uses the information contained therein to resolve inter-library
dependencies on its own.  When a library is requested that has no
associated *.la file, it simply calls dlopen with a ".so" suffix.
When this ".so" library can't be opened it is simply ignored (with a
warning).

So the rule is: you must make sure that you have correct inter-library
dependencies.  Either use libtool, which will put these dependencies
into its *.la files where we can find them; or build your shared
libraries `by hand', so that dlopen can resolve the dependencies.  In
either case, do not include static libraries in the inter-library
dependencies.

As an exception, you do not need to include the Guile libraries
(-lguile, -lqthreads, etc) in your dependencies, because they are
always there.  You *do* need -lguilegtk and the Gtk libraries, tho.

We need to use the RTLD_GLOBAL flag to make all this happen, but
unfortunately, Guile calls dlopen without this flag.  This is why we
have a very simple libguiledlopenhelper.

The code in gtk/dynlink.scm tries to emulate the way the linker
searches for libraries: First, each directory in LD_LIBRARY_PATH is
tried, then "/usr/local/lib", "/usr/lib", "/lib", in that order.

I expect things to change for the better in the future, of course, but
shared libraries and dlopening are a very effective time-sink, it
seems.

UPDATE: when configure detects a recent version of libtool that looks
like it can handle inter-library dependencies on its own,
gtk/dynlink.scm just opens the library and does not try to be clever
about *.la files.  Libtool 1.2e works for me in this way.


Wrapping Your Own Widgets
-------------------------

There is a complete autoconfed/automade example for this.

After installing the guile-gtk package, change to the examples/
directory:

  % cd examples
  % ./configure
  % make

Again: you need to have guile-gtk installed for this to work!

Now you should have a new executable `guile-foo' that has glue code
for the function `foo-new' in the `(gtk foo)' module.  You can test it
thus:

  % ./guile-foo -s test-foo.scm

Here is the general procedure:

When you have some Gtk widgets that are not described in gtk.defs or
gdk.defs, you can use build-guile-gtk to automatically generate glue
code for them.  Here is how to wrap the hypothetical GtkFoo widget and
its related function gtk-foo-new.  They are assumed to live in gtkfoo.h
and libfoo.

- Write the foo.defs file

  ;; We use the types defined in gtk-1.2.defs

  (import "gtk-1.2.defs")

  (define-object GtkFoo (GtkWidget))

  (define-func gtk_foo_new
    GtkFoo
    ())

  (options
    ;; Includes needed to compile code that uses GtkFoo.
    (includes "#include <gtkfoo.h>")
    ;; The name of the generated initialization function.
    (init-func "foo_init_glue")
    ;; Libraries needed to link. libguilefoo will contain
    ;; the glue code and libfoo contains the widget itself.
    (libs "-lguilefoo -lfoo"))

- Write the foo.scm file

  (define-module (gtk foo)
    :use-module (gtk dynlink))

  ;; Call the init function, either using a pre-linked -lguilefoo or
  ;; dynamically linking it.
  (merge-compiled-code "foo_init_glue" "libguilefoo")

- Generate the glue code

  % build-guile-gtk glue foo.defs >foo-glue.c

- Compile the glue code into a shared library, using libtool

  [This will be simplified and then explained.  Right now, keep in
   mind to use gtk-config and build-guile to get all necessary flags and
   libraries.]

  % libtool --mode=link ... -o libguilefoo.la ...

- Install the shared library, again using libtool.

  % libtool --mode=install cp libguilefoo.la <exec_prefix>/lib/

- Install the foo.scm file

  % cp foo.scm <prefix>/share/guile/gtk/foo.scm

- Install the *.defs files for other people to use.

  % cp foo.defs foo.defs.guile <prefix>/share/guile-gtk/

Now you should be able to just (use-modules (gtk foo)).  When dynamic
linking does not work for you, you might want to try

  % build-guile-gtk link foo.defs -o guile-foo

This will link a new executable named guile-foo that will have the
libguilefoo library pre-linked into it so that you do not need
dynamic-link.  This will work with any number of *.defs files.


Composite Types and `call-by-reference'
---------------------------------------

Guile-gtk has (still experimental) support for composite types like
lists and vectors.  On the Gtk+ side, the types GSList (singly linked
list), GList (doubly linked list), and counted and fixed length
vectors are supported.  On the Scheme side, you can use Scheme lists
and Scheme vectors.  You can mix these types freely.  That is you can
use a list on the Scheme side to represent a vector on the Gtk+ side,
and vice versa.

Composite types have modes associated with them.  They can be `in',
`out', or `inout'.  When a composite type is marked with a `in' mode,
the Gtk+ side is not allowed to make changes to the contents of the
composite.  When it is `out', it must initialize the contents before
it returns and is not allowed to read it prior to initialization.
Consequently, mode `inout' indicates that the Gtk+ side may both read
and write the composite freely, and that the contents has been
initialized by the caller.  On the Scheme side, mode `out' turns off
type checking for the contents of composites and the initial values of
the composite passed to Gtk+ will be undefined.

The default mode is `in'.

The available variations are:

  [ *.defs file syntax ]             [ C side function arguments ]
  [ Comment ]

  (slist <type> [<mode>])            GSList *lst
  For singly linked lists.  Scheme owns the memory of the list nodes.

  (list <type> [<mode>])             GList *lst
  For doubly linked lists.  Scheme owns the memory of the list nodes.

  (cvec <type> [<mode>])             int len, <type>* vec
  For counted vectors.  The length of the Scheme composite is passed
  to the Gtk+ function.  Scheme owns the memory of the vector.

  (cvecr <type> [<mode>])            <type>* vec, int len
  For counted vectors, reverse order of arguments.  Scheme owns the
  memory of the vector.

  (fvec <type> <len> [<mode>])       <type>* vec
  For fixed length vectors.  The Scheme composite must be of length <len>.
  Scheme owns the memory of the vector.
  
  (ret <type>)                       <type>* vec
  Abbreviation for (fvec <type> 1 out)

These composite types are also intended to be used for
call-by-reference arguments.  Neither Scheme nor C really has these
425
call-by-reference arguments, so guile-gtk won't either.  In C, you
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
would pass a pointer to the desired object; in Scheme you use a
one-element list or a vector of length one.  For guile-gtk, these
types are modelled with a `fvec' composite type of length one and mode
out, or equivalently but shorter with the `ret' type.

For example, when you have a Gtk+ function with a prototype like

    void gtk_foo (char **strptr);

that deposits some string in *STRPTR (whose memory should be taken
over by the caller), you can wrap it like this:

     (define-func gtk_foo
       none
       ((ret string) strptr))

Usage is a little cumbersome from Scheme.  This code snippet

     (let ((strptr (list #f)))
       (gtk-foo strptr)
       (car strptr))

would yield the returned string.


Documentation
-------------

Nothing available yet, but the Scheme interface to Gtk is very similar
to the C one.  Almost all functions take the same arguments as their C
counterparts.  Exceptions are:

- To access the Gtk functions, you need to use the `(gtk gtk)'
  module.  You can do this with

    (use-modules (gtk gtk))

  or

    (define-module (your module)
      :use-modules (gtk gtk))

  Likewise, you need to use the `(gtk gdk)' module if you want to use
  functions from Gdk.

- Booleans are expressed with Scheme's real boolean values #f and #t.

- Enumerations are expressed with symbols.  For example
  GTK_WINDOW_TOPLEVEL is written as 'toplevel.  The symbols should be
  easy to guess from their C counterparts, but they are not completely
  systematic.  See gtk.defs for the definite details.

- Flags (or bitmasks) are expressed as lists of symbols.  For example
  GTK_EXPAND|GTK_FILL is '(expand fill).

- Callbacks don't take a client-data argument, so you don't have to
  specify one to gtk_signal_connect, or gtk_timeout_add, etc.

- Signal handlers don't get the Object as their first argument.  In my
  view, this would be more often annoying than helpful.

- NULL pointers are expressed as #f.

- Some parameters are optional and get a default value when left
  unspecified.

- Each type that is derived from GtkObject has an associated predicate
  function to test whether a Scheme value is of that type.  The
  predicate for GtkObject is called `gtk-object?', the one for
  GtkRadioButton `gtk-radio-button?', etc.

- gtk-radio-button-new and gtk-radio-button-new-with-label don't take
  a list as their group argument but a GtkWidget whose group is used
  instead.

- Likewise for gtk-radio-menu-item.

- Colors and fonts can be specified with strings, like "red" or
  "fixed".  If you want to convert from these strings to the real
  values (for efficiency reasons, say) you can use the functions
  `gdk-color-intern' and `gdk-font-intern'.

- It might be that your code is loaded into an application that
  already has an event loop running (or will run one after
  initialization is complete).  You should then restrain from calling
  `gtk-main' yourself (except maybe for modal dialog boxes) and you
  should not terminate the program.

  You can use the function `gtk-standalone?' to find out whether your
  code is `standalone', i.e. whether you should call `gtk-main'
  yourself.

  For convenience you can also use

     gtk-standalone-main TOPLEVEL

  This will arrange things so that the program is terminated with
  `gtk-exit' when the TOPLEVEL widget is destroyed and will call
  `gtk-main'.  All these things will only happen when
  `gtk-standalone?' returns true.


And all the things I forgot about.  Be sure to read the NEWS file as
it is currently the only place that documents most details.
"examples/calc.scm" is quite heavily commented, but does not explain
Gtk programming.  It is more an example about extensibility.

Have fun!

Marius Vollmer
Ariel Rios