1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
Gtk-2 Binding for Lua 5.1
=========================
After finding the combination of Python and Gtk2 very useful, but somewhat
bloated, I looked for another possibility. gtk-server (at gtk-server.org) is
already a step in the right direction, but for big projects it looks rather
limited. As the previous lua-gnome project apparently is defunct, I wrote a
small library to interface Lua with Gtk-2.0 (currently Lua 5.1 and Gtk 2.12.x).
It is supposed to work under Linux and also Windows.
Features:
- all GLib, GDK, Gtk, Atk, Pango, GIO (and more) functions and
structures are available
- automatic memory and type handling
- connect() any signals to Lua functions (callbacks)
- object-oriented calls are possible like win:show_all()
- small footprint
- probably efficient, too, but I'd have to do some tests
Memory management: GLib has reference counting, which is used, and of course
Lua has its garbage collection. In general, you don't have to worry about
memory allocation and freeing, that happens automatically. In some corner
cases you need to free memory yourself, though.
Gtk returns pointers to widgets, these are stored in small user data objects
(containing only the pointer and a meta class pointer).
Callbacks: several parameters are passed:
- first any additional parameters the user has specified for the gtk:connect
call. Tradionally (gtk, pygtk) these additional parameters are passed last
to the signal handler, but I want to have "self" as the first parameter
- next is the widget that originated the signal
- finally all the parameters that gtk passes for this signal
Usage: after proper installation, this should work:
require "gtk2"
win = gtk.window_new(gtk.GTK_WINDOW_TOPLEVEL)
win:connect('destroy', gtk.main_quit)
win:show()
gtk.main()
The list of Gtk functions, structures and enums is generated by a Lua script
(included) from the output of gccxml. The resulting data is dumped into
several compileable .c files and are compiled into the library and is then
applicable to the Windows platform as well.
WARNING: this is BETA software, so expect some misbehavior. Please send
feedback to wolfgang.oertl@gmx.at.
Data structures
===============
Callbacks: when you call connect a signal, a Lua function is provided by your
application. A callback_info structure is allocated per signal connection. It
contains following information:
ref Reference to a Lua closure
L the Lua State this belongs to
query Information about the signal from g_type_query.
When Gtk calls such a callback, then the function do_callback builds a proper
Lua stack and invokes the user provided Lua function.
About GtkWindow refcounting
---------------------------
When you create a GtkWindow with gtk.window_new(), the returned window does not
have a floating reference as is usual with other widgets. The reason is that
this widget is in the toplevel_list of Gtk; therefore it has two regular
references: one for the Lua proxy object, and one from Gtk. If you just
"forget" about the GtkWindow, it will not be garbage collected. Instead, you
have to call w:destroy() on it.
Performance
===========
Some tests with valgrind show that this binding, as well as Lua itself,
ccount for only a minimal part of the runtime. Further optimization is
therefore currently not a goal.
# make sure that the script calls gtk.set_debug_flags("valgrind")
valgrind --tool=callgrind lua [script]
kcachegrind
Enum encoding
=============
A list of about 5000 constants are currently defined; most of them are
ENUMs, but lots of integers (a few negative) and strings are also stored. You
can access them directly with gtk.CONSTANT_NAME, like gtk.GTK_WINDOW_TOPLEVEL
or gtk.GTK_STOCK_OK.
Bits of the first byte: TSNh hhhh
T if set, a type_idx is included
S if set, this is a string.
N if set, this is a negative number; unused for strings
h if T==1, high order bits of type_idx; else for a number,
high order bits of the value.
If T is set, another byte follows with the lower 8 bits of the type_idx.
if S is set, the string follows (without terminating zero byte)
Otherwise, an integer follows, with the higher order bytes first.
Encoding happens in script/common.lua, decoding in src/data.c.
|