All lgi functionality is exported through lgi
module. To access it,
use standard require
construct, e.g.:
local lgi = require 'lgi'
Note that lgi does not use module
function, so it does not
automatically insert itself into globals, the return value from
require
call has to be used.
To use any introspection-enabled library, it has to be imported first.
Simple way to import it is just referencing its name in lgi
namespace, like this:
local GLib = lgi.GLib
local GObject = lgi.GObject
local Gtk = lgi.Gtk
This imports the latest version of the module which can be found.
When exact version is requested, use lgi.require(modulename, version)
:
local Gst = lgi.require('Gst', '0.10')
Importing library creates table containing all elements which are present in the library namespace - all classes, structures, global functions, constants etc. All those elements are directly accessible, e.g.
assert(GLib.PRIORITY_DEFAULT == 0)
Note that all elements in the namespace are lazy-loaded to avoid
excessive memory overhead and initial loading time. To force
eager-loading, all namespaces (and container elements in them, like
classes, structures, enums etc) contains _resolve(deep)
method, which
loads all contents eagerly, possibly recursively if deep
argument is
true
. So e.g.
dump(Gtk.Widget:_resolve(true), 3)
prints everything available in Gtk.Widget class, and
dump(Gio:_resolve(true), 5)
dumps the whole contents of Gio package.
Note: the dump
function used in this manual is part of
cli-debugger
Lua package. Of course, you can use any kind of
table-dumping facility you are used to instead.
In order to call methods and access properties and fields from Lua, a mapping between GLib types and Lua types is established.
void
is ignored, does not produce any Lua valuegboolean
is mapped to Lua'sboolean
type, withtrue
andfalse
values- All numeric types are mapped to Lua's
number
type - Enumerations are primarily handled as strings with uppercased GType nicks, optionally the direct numeric values are also accepted.
- Bitflags are primarily handled as lists or sets of strings with uppercased GType nicks, optionally the direct numeric values are also accepted.
gchar*
string is mapped to Lua asstring
type, UTF-8 encoded- C array types and
GArray
is mapped to Lua tables, using array part of the table. Note that although in C the arrays are 0-based, when copied to Lua table, they are 1-based (as Lua uses 1-based arrays). GList
andGSList
is also mapped to Lua array part of tables.GHashTable
is mapped to Lua table, fully utilizing key-value and GHashTable's key and value pairs.- C arrays of 1-byte-sized elements (i.e. byte buffers) is mapped to
Lua
string
instead of tables, although when going Lua->GLib direction, tables are also accepted for this type of arrays. - GObject class, struct or union is mapped to lgi instances of
specific class, struct or union. It is also possible to pass
nil
, in which case theNULL
is passed to C-side (but only if the annotation(allow-none)
of the original C method allows passingNULL
). gpointer
are mapped to Lualightuserdata
type. In Lua->GLib direction, following values are accepted forgpointer
type:- Lua
string
instances - Instances of lgi classes, structs or unions
- Binary buffers (see below)
- Lua
When calling GLib functions, following conventions apply:
- All input arguments are mapped to Lua inputs
- Return value is the first Lua return value
- All output arguments follow the return value
- In/Out arguments are both accepted as input and are also added into Lua returns.
- Functions reporting errors through
GError **
as last argument use Lua standard error reporting - they typically return boolean value indicating either success or failure, and if failure occurs, following return values represent error message and error code.
GLib based libraries often use boolean return value indicating whether
logically-output argument is filled in or not. Typical example is
gboolean gtk_tree_model_get_iter_first(GtkTreeModel *tree_model, GtkTreeIter *iter)
, where iter
is filled in case of success, and
untouched in case of failure. Normal binding of such function feels a
bit unnatural in Lua:
local ok, iter = model:get_iter_first()
-- Even in case of failure, iter contains new 0-initialized
-- instance of the iterator, so following line is necessary:
if not ok then iter = nil end
To ease usage of such method, lgi avoids returning first boolean
return. If C function returns false
in this case, all other output
arguments are returned as nil
. This means that previous example
must be instead written simply as:
local iter = model:get_iter_first()
When some GLib function or method requires callback argument, a Lua
function should be provided (or userdata or table implementing
__call
metamethod), and position for callback context (usually
called user_data
in GLib function signature) should be ignored
completely. Callbacks are invoked in the context of Lua coroutine
which invoked the original call, unless the coroutine is suspended -
in this, case a new coroutine is automatically created and callback is
invoked in this new context.
Callback arguments and return values are governed by the same rules of
argument and type conversions as written above. If the Lua callback
throws an error, the error is not caught by the calling site,
instead propagated out (usually terminating unless there is some
pcall
in the call chain).
It is also possible to provide coroutine instance as callback
argument. In this case, the coroutine is resumed, providing callback
arguments as parameters to resume (therefore they are return values of
coroutine.yield()
call which suspended the coroutine passed as
callback argument). The callback is in this case considered to return
when either coroutine terminates (in this case, callback return
value(s) are coroutine final result(s)) or yields again (in this case,
callback return value(s) are arguments to coroutine.yield()
call).
This mode of operation is very useful when using Gio-style
asynchronous calls. However, it is recommended to use lgi-specific
Gio.Async
facility for this purpose, as described in its own
documentation, because it wraps and hides many intricacies which arise
with coroutines and mainloop integration.
Classes are usually derived from GObject
base class. Classes
contain entities like properties, methods and signals and provide
inheritance, i.e. entities of ancestor class are also available in all
inherited classes. lgi supports Lua-like access to entities using .
and :
operators.
There is no need to invoke any memory management GObject controls,
like ref
or unref
methods, because lgi handles reference
management transparently underneath. In fact, calling these low-level
methods can probably always be considered either as a bug or
workaround for possible bug in lgi :-)
To create new instance of the class (i.e. new object), call class declaration as if it is a method:
local window = Gtk.Window()
Optionally, it is possible to pass single argument, table containing entity name mapping to entity value. This way it is possible to initialize properties, fields and even signal handlers in the class construction:
local window = Gtk.Window {
title = "Title",
on_destroy = function() print("Destroyed") end
}
For some classes, which behave like containers of other things, lgi
allows adding also a list of children into the array part of the
argument table, which contains children element to be added. A
typical example is Gtk.Container
, which allows adding element in the
constructor table, allowing construction of the whole widget
hierarchy in Lua-friendly way:
local window = Gtk.Window {
title = "Title",
on_destroy = function() print("Destroyed") end,
Gtk.Grid {
Gtk.Label { label = "Contents", expand = true },
Gtk.Statusbar {}
}
}
There is also possibility to create instances of classes for which the
introspection typelib data is not available, only GType is known. Use
GObject.Object.new()
as illustrated in following sample:
local gtype = 'ForeignWidget'
local widget = GObject.Object.new(gtype)
local window = Gtk.Window { title = 'foreign', widget }
Methods are functions grouped inside class (or interface)
declarations, accepting pointer to class instance as first argument.
Most usual technique to invoke method is using :
operator,
e.g. window:show_all()
. This is of course identical with
window.show_all(window)
, as is convention in plain Lua.
Method declaration itself is also available in the class and it is
possible to invoke it without object notation, so previous example can
be also rewritten as Gtk.Window.show_all(window)
. Note that this
way of invoking removes dynamic lookup of the method from the object
instance type, so it might be marginally faster. However, in case
that window
is actually instance of some GtkWindow
descendant,
lets say MyWindow
, which also defined my_window_show_all()
method,
there will be a difference: window:show_all()
will invoke
my_window_show_all(window)
, while Gtk.Window.show_all(window)
will
of course invoke non-specialized gtk_widget_show_all(window)
.
Static methods (i.e. functions which do not take class instance as
first argument) are usually invoked using class namespace,
e.g. Gtk.Window.list_toplevels()
. Very common form of static
methods are new
constructors, e.g. Gtk.Window.new()
. Note that in
most cases, new
constructors are provided only as convenience for C
programmers, in lgi it might be preferable to use window = Gtk.Window { type = Gtk.WindowType.TOPLEVEL }
instead of window = Gtk.Window.new(Gtk.WindowType.TOPLEVEL)
.
Object properties are accessed simply by using .
operator.
Continuing previous example, we can write window.title = window.title .. ' - new'
. Note that in GObject system, property and signal names
can contain -
character. Since this character is illegal in Lua
identifiers, it is mapped to _
, so can-focus
window property is
accessed as window.can_focus
.
Signals are exposed as on_signalname
entities on the class
instances.
Assigning Lua function connects that function to the signal. Signal routine gets object as first argument, followed by other arguments of the signal. Simple example:
local window = Gtk.Window()
window.on_destroy = function(w)
assert(w == window)
print("Destroyed", w)
end
Note that because of Lua's syntactic sugar for object access and function definition, it is possible to use signal connection even in following way:
local window = Gtk.Window()
function window:on_destroy()
assert(self == window)
print("Destroyed", self)
end
Reading signal entity provides temporary table which can be used for connecting signal with specification of the signal detail (see GObject documentation on signal detail explanation). An example of handler which is notified whenever window is activated or deactivated follows:
local window = Gtk.Window()
window.on_notify['is-active'] = function(self, pspec)
assert(self == window)
assert(pspec.name == 'is-active')
print("Window is active:", self.is_active)
end
Both forms of signal connection connect handler before default signal
handler. If connection after default signal handler is wanted (see
G_CONNECT_AFTER
documentation for details), the most generic
connection call has to be used: object.on_signalname:connect(target, detail, after)
. Previous example rewritten using this connection
style follows:
local window = Gtk.Window()
local function notify_handler(self, pspec)
assert(self == window)
assert(pspec.name == 'is-active')
print("Window is active:", self.is_active)
end
window.on_notify:connect(notify_handler, 'is-active', false)
Emitting existing signals is usually needed only when implementing subclasses of existing classes. Simplest method to emit a signal is to 'call' the signal on the class instance:
local treemodel = <subclass implementing Gtk.TreeModel>
treemodel:on_row_inserted(path, iter)
lgi assigns real class types to class instances dynamically, using runtime GObject introspection facilities. When new classes instance is passed from C code into Lua, lgi queries the real type of the object, finds the nearest type in the loaded repository and assigns this type to the Lua-side created proxy for the object. This means that there is no casting needed in lgi (and there is also no casting facility available).
Hopefully everything can be explained in following example. Assume
that demo.ui
is GtkBuilder file containing definition of GtkWindow
labeled window1
and GtkAction
called action1
(among others).
local builder = Gtk.Builder()
builder:add_from_file('demo.ui')
local window = builder:get_object('window1')
-- Call Gtk.Window-specific method
window:iconify()
local action = builder:get_object('action1')
-- Set Gtk.Action-specific property
action.sensitive = false
Although Gtk.Builder.get_object()
method is marked as returning
GObject*
, lgi actually checks the real type of returned object and
assigns proper type to it, so builder:get_object('window1')
returns
instance of Gtk.Window
and builder:get_object('action1')
returns
instance of Gtk.Action
.
Another mechanism which allows complete lack of casting in lgi is automatic interface discovery. If some class implements some interface, the properties and methods of the interface are directly available on the class instance.
GObject has the notion of object class. There are sometimes useful
methods defined on objects class, which are accessible to lgi using
object instance pseudo-property _class
. For example, to list all
properties registered for object's class, GObject library provides
g_object_class_list_properties()
function. Following sample lists
all properties registered for the given object instance.
function dump_props(obj)
print("Dumping properties of ", obj)
for _, pspec in pairs(obj._class:list_properties()) do
print(pspec.name, pspec.value_type)
end
end
Running dump_props(Gtk.Window())
yields following output:
Dumping props of lgi.obj 0xe5c070:Gtk.Window(GtkWindow)
name gchararray
parent GtkContainer
width-request gint
height-request gint
visible gboolean
sensitive gboolean
... (and so on)
To query whether given Lua value is actually an instance of specified
class or subclass, class types define is_type_of
method. This
class-method takes one argument and checks, whether given argument as an
instance of specified class (or implements specified interface, when
called on interface instances). Following examples demonstrate usage of
this construct:
local window = Gtk.Window()
print(Gtk.Window:is_type_of(window)) -- prints 'true'
print(Gtk.Widget:is_type_of(window)) -- prints 'true'
print(Gtk.Buildable:is_type_of(window)) -- prints 'true'
print(Gtk.Action:is_type_of(window)) -- prints 'false'
print(Gtk.Window:is_type_of('string')) -- prints 'false'
print(Gtk.Window:is_type_of(nil)) -- prints 'false'
There is also possibility to query the type-table from instantiated
object, using _type
property.
-- Checks, whether 'unknown' conforms to the type of the 'template'
-- object.
function same_type(template, unknown)
local type = template._type
return type:is_type_of(unknown)
end
It is possible to implement subclass of any existing class in pure Lua. The reason to do so is to implement virtual methods of parent class (and possibly one or more interfaces).
In order to create subclass, lgi requires to create package
first,
which is basically namespace where the new classes will live. To
create a package, use lgi.package
function:
-- Create MyApp package
local MyApp = lgi.package 'MyApp'
Once the package is created, it is possible to reference it from lgi
as any other existing namespace:
local Gtk = lgi.Gtk
local MyApp = lgi.MyApp
To create subclass, use package's method class(name, parent[, ifacelist])
:
MyApp:class('MyWidget', Gtk.Widget)
MyApp:class('MyModel', GObject.Object, { Gtk.TreeModel })
After that, newly created class behaves exactly the same as classes picked up from GObjectIntrospection namespaces, like shown in following examples:
local widget = MyApp.MyWidget()
widget:show()
Note that it is important to override virtual methods before any instance of the derived class (see chapter about virtual methods below).
To make subclass useful, it is needed to override some of its virtual
methods. Existing virtual methods are prefixed with do_
. In order
to call inherited virtual methods, it is needed to use an explicit
function reference. There is an automatic property called priv
which is plain Lua table and allows subclass implementation to store
some internal status. All these techniques are illustrated in
following sample:
function MyApp.MyWidget:do_show()
if not self.priv.invisible then
-- All three lines perform forwarding to inherited virtual:
Gtk.Widget.do_show(self)
-- or:
MyApp.MyWidget._parent.do_show(self)
-- or:
self._type._parent.do_show(self)
end
end
-- Convenience method for setting MyWidget 'invisible'
function MyApp.MyWidget:set_invisible(invisible)
self.priv.invisible = invisible
end
The important fact is that virtual method overrides are picked up only up to the first instantiation of the class or inheriting new subclass from it. After this point, virtual function overrides are ignored.
To add new property for derived class, a new GObject.ParamSpec
instance describing property must be added into _property
table of
derived class. This must be done before first instantiation of the class.
By default, the value of the property is mirrored in priv
table of
the instance. However, it is possible to specify custom getter and
setter method in _property_set
and _property_get
tables. Both
approaches are illustrated in the following example with property
called my_label
MyApp.MyWidget._property.my_label = GObject.ParamSpecString(
'my_label', 'Nick string', 'Blurb string', 'def-value',
{ 'READABLE', 'WRITABLE', 'CONSTRUCT' })
function MyApp.MyWidget._property_set:my_label(new_value)
print(('%s changed my_label from %s to %s'):format(
self, self.priv-my_label, new_value))
self.priv.my_label = new_value
end
local widget = MyApp.MyWidget()
-- Access through GObject's property machinery
widget.my_label = 'label1'
print(widget.my_label)
-- Direct access to underlying storage
print(widget.priv.my_label)
Structures and unions are supported in a very similar way to classes. They have only access to methods (in the same way as classes) and fields, which are very similar to the representation of properties on the classes.
Structure instances are created by 'calling' structure definition,
similar to creating new class: local color = Gdk.RGBA()
. For
simplest structures without constructor methods, the new structure is
allocated and zero-initialized. It is also possible to pass table
containing fields and values to which the fields should be
initialized: local blue = Gdk.RGBA { blue = 1, alpha = 1 }
.
If the structure has defined any constructor named new
, it is
automatically mapped by lgi to the structure creation construct, so
calling local main_loop = GLib.MainLoop(nil, false)
is exactly
equivalent with local main_loop = GLib.MainLoop.new(nil, false)
, and
local color = Clutter.Color(0, 0, 0, 255)
is exactly equivalent with
local color = Clutter.Color.new(0, 0, 0, 255)
.
Structure methods are called in the same way as class methods:
struct:method()
, or StructType.method()
. For example:
local loop = GLib.MainLoop(nil, false)
loop:run()
-- Following line is equivalent
GLib.MainLoop.run(loop)
Fields are accessed using .
operator on structure instance, for example
local color = Gdk.RGBA { alpha = 1 }
color.green = 0.5
print(color.red, color.green, color.alpha)
-- Prints: 0 0.5 1
lgi primarily maps enumerations to strings containing uppercased nicks of enumeration constant names. Optionally, a direct enumeration value is also accepted. Similarly, bitflags are primarily handled as sets containing uppercased flag nicks, but also lists of these nicks or direct numeric value is accepted. When a numeric value cannot be mapped cleanly to the known set of bitflags, the remaining number is stored in the first array slot of the returned set.
Note that this behavior changed in lgi 0.4; up to that alpha release, lgi handled enums and bitmaps exclusively as numbers only. The change is compatible in Lua->C direction, where numbers still can be used, but incompatible in C->Lua direction, where lgi used to return numbers, while now it returns either string with enum value or table with flags.
In order to retrieve real enum values from symbolic names, enum and
bitflags are loaded into repository as tables mapping symbolic names
to numeric constants. Fro example, dumping Gtk.WindowType
enum
yields following output:
dump(Gtk.WindowType)
["table: 0xef9bc0"] = { -- table: 0xef9bc0
TOPLEVEL = 0;
POPUP = 1;
};
so constants can be referenced using Gtk.WindowType.TOPLEVEL
construct, or directly using string 'TOPLEVEL'
when a
Gtk.WindowType
is expected.
There is another facility in lgi, which allows backward mapping of numeric constants to symbolic names. Indexing enum table with number actually provides symbolic name to which the specified constant maps:
print(Gtk.WindowType[0])
TOPLEVEL
print(Gtk.WindowType[2])
nil
Indexing bitflags table with number provides table containing list of all symbolic names which make up the requested value:
dump(Gtk.RegionFlags)
["table: 0xe5dd10"] = { -- table: 0xe5dd10
ODD = 2;
EVEN = 1;
SORTED = 32;
FIRST = 4;
LAST = 8;
dump(Gtk.RegionFlags[34])
["table: 0xedbba0"] = { -- table: 0xedbba0
SORTED = 32;
ODD = 2;
};
This way, it is possible to check for presence of specified flag very easily:
if Gtk.RegionFlags[flags].ODD then
-- Code handling region-odd case
endif
If the value cannot be cleanly decomposed to known flags, remaining bits are accumulated into number stored at index 1:
dump(Gtk.RegionFlags[51])
["table: 0x242fb20"] = { -- table: 0x242fb20
EVEN = 1;
SORTED = 32;
[1] = 16;
ODD = 2;
};
To construct numeric value which can be passed to a function expecting an enum, it is possible to simply add requested flags. However, there is a danger if some definition contains multiple flags , in which case numeric adding produces incorrect results. Therefore, it is possible to use bitflags pseudoconstructor', which accepts table containing requested flags:
=Gtk.RegionFlags { 'FIRST', 'SORTED' }
36
=Gtk.RegionFlags { Gtk.RegionFlags.ODD, 16, 'EVEN' }
19
Lua platform does not allow running real concurrent threads in single Lua state. This rules out any usage of GLib's threading API. However, wrapped libraries can be using threads, and this can lead to situations that callbacks or signals can be invoked from different threads. To avoid corruption which would result from running multiple threads in a single Lua state, lgi implements one internal lock (mutex) which protects access to Lua state. lgi automatically locks (i.e. waits on) this lock when performing C->Lua transition (invoking Lua callback or returning from C call) and unlocks it on Lua->C transition (returning from Lua callback or invoking C call).
In a typical GLib-based application, most of the runtime is spent inside mainloop. During this time, lgi lock is unlocked and mainloop can invoke Lua callbacks and signals as needed. This means that lgi-based application does not have to worry about synchronization at all.
The only situation which needs intervention is when mainloop is not
used or a different form of mainloop is used (e.g. Copas scheduler, Qt
UI etc). In this case, lgi lock is locked almost all the time and
callbacks and signals are blocked and cannot be delivered. To cope
with this situation, a lgi.yield()
call exists. This call
temporarily unlocks the lgi lock, letting other threads to deliver
waiting callbacks, and before returning the lock is closed back. This
allows code which runs foreign, non-GLib style of mainloop to stick
lgi.yield()
calls to some repeatedly invoked place and thus allowing
delivery of callbacks from other threads.
GLib provides generic logging facility using g_message
and similar C
macros. These utilities are not directly usable in Lua, so lgi
provides layer which allows logging messages using GLib logging
facilities and controlling behavior of logging methods.
All logging is controlled by lgi.log
table. To allow logging in
lgi-enabled code, lgi.log.domain(name)
method exists. This method
returns table containing methods message
, warning
, critical
,
error
and debug
methods, which take format string optionally
followed by inserts and logs specified string. An example of typical
usage follows:
local lgi = require 'lgi'
local log = lgi.log.domain('myapp')
-- This is equivalent of C 'g_message("A message %d", 1)'
log.message("A message %d", 1)
-- This is equivalent to C 'g_warning("Not found")'
log.warning("Not found")
Note that format string is formatted using Lua's string.format()
, so
the rules for Lua formatting strings apply here.
There might be some scenarios where it is important to either export
objects or records created in Lua into C code or vice versa. lgi
allows transfers using Lua lightuserdata
type. To get native
pointer to the lgi object, use _native
attribute of the object. To
create lgi object from external pointer, it is possible to pass
lightuserdata with object pointer to type constructor. Following
example illustrates both techniques:
-- Create Lua-side window object.
local window = Gtk.Window { title = 'Hello' }
-- Get native pointer to this object.
local window_ptr = window._native
// window_ptr can be now passed to C code, which can use it.
GtkWindow *window = lua_touserdata (L, x);
char *title;
g_object_get (window, "title", &title);
g_assert (g_str_equal (title, "Hello"));
g_free (title);
// Create object on the C side and pass it to Lua
GtkButton *button = gtk_button_new_with_label ("Foreign");
lua_pushlightuserdata (L, button);
lua_call (L, ...);
-- Retrieve button on the Lua side.
assert(type(button) == 'userdata')
window:add(Gtk.Button(button))
Note that while the example demonstrates objects, the same mechanism works also for structures and unions.
Although GObject library is already covered by gobject-introspection, most of the elements in it are basic object system building blocks and either need or greatly benefit from special handling by lgi.
Contrary to C GType
representation (which is unsigned number), lgi
represents GType by its name, as a string. GType-related constants
and methods useful for handling GType are present in GObject.Type
namespace.
Fundamental GType names are imported as constants into GObject.Type
namespace, so that it is possible to use for example
GObject.Type.INT
where G_TYPE_INT
would be used in C code.
Following constants are available:
NONE
,INTERFACE
,CHAR
,UCHAR
,BOOLEAN
,INT
,UINT
,LONG
,ULONG
,INT64
,UINT64
,ENUM
,FLAGS
,FLOAT
,DOUBLE
,STRING
,POINTER
,BOXED
,PARAM
,OBJECT
,VARIANT
Moreover, functions operating on GType
are also present in
GObject.Type
namespace:
parent
,depth
,next_base
,is_a
,children
,interfaces
,query
,fundamental_next
,fundamental
There is special new method, Type.type(gtype)
which returns lgi
native type representing specified gtype. For example:
assert(Gtk.Window == GObject.Type.type('GtkWindow'))
assert(Gtk.WidgetPath == GObject.Type.type('GtkWidgetPath'))
When transferring GType
value from Lua to C (e.g. calling function
which accepts argument of GType
), it is possible to use either
string with type name, number representing numeric GType
value, or
any loaded component which has its type assigned. Some examples of
GType
usage follow:
lgi = require 'lgi'
GObject = lgi.GObject
Gtk = lgi.Gtk
print(GObject.Type.NONE)
print(GObject.Type.name(GObject.Type.NONE))
-- prints "void" in both cases
print(GObject.Type.name(Gtk.Window))
-- prints "GtkWindow"
print(GObject.Type.is_a(Gtk.Window, GObject.Type.OBJECT))
-- prints "true"
print(GObject.Type.parent(Gtk.Window))
-- prints "GtkBin"
lgi does not implement any automatic GValue
boxing or unboxing,
because this would involve guessing GType
from Lua value, which is
generally unsafe. Instead, an easy to use and convenient wrappers for
accessing GValue
type and contents are provided.
To create new GObject.Value
instances, use similar method as for
creating new structures or classes, i.e. 'call' GObject.Value
type.
The call has two optional arguments, specifying GType
of newly
created GValue
and optionally also the contents of the value. A few
examples for creating new values follow:
local lgi = require 'lgi'
local GObject = lgi.GObject
local Gtk = lgi.Gtk
local empty = GObject.Value()
local answer = GObject.Value(GObject.Type.INT, 42)
local null_window = GObject.Value(Gtk.Window)
local window = GObject.Value(Gtk.Window, Gtk.Window())
GObject.Value
adds two new virtual properties, called gtype
and
value
. gtype
contains actual type of the value, while value
provides access to the contents of the value. Both properties are
read/write. Reading of them queries current GObject.Value
state,
i.e. reading value
performs actual GValue
unboxing. Writing
value
performs value boxing, i.e. the source Lua item is attempted
to be stored into the GObject.Value
. Writing gtype
attempts to
change the type of the value, and in case that value already has a
contents, it also converts contents to the new type (using
g_value_transform()
). Examples here continue using the values
created in previous section example:
assert(empty.gtype == nil)
assert(empty.value == nil)
assert(answer.gtype == GObject.Type.INT)
assert(answer.value == 42)
assert(null_window.gtype == 'GtkWindow')
assert(null_window.value == nil)
empty.gtype = answer.gtype
empty.value = 1
assert(empty.gtype == GObject.Type.INT)
assert(empty.value == 1)
answer.gtype = GObject.Type.STRING)
assert(answer.value == '42')
Although GObject.Value
provides most of the GValue documented
methods (e.g. g_value_get_string()
is accessible as
GObject.Value.get_string()
and getting string contents of the value
instance can be written as value:get_string()
), value
and gtype
abstract properties are recommended to be used instead.
Similar to GObject.Value, no automatic GClosure boxing is implemented.
To create a new instance of GClosure
, 'call' closure type and
provide Lua function as an argument:
closure = GObject.Closure(func)
When the closure is emitted, a Lua function is called, getting
GObject.Value
as arguments and expecting to return GObject.Value
instance.